diff --git a/README.md b/README.md index e30f96e..7fe150b 100644 --- a/README.md +++ b/README.md @@ -31,21 +31,24 @@ To generate the documentation for this library, run e.g. `stack haddock`. ## Modular term representation -The `PlutusCore.TermF` module exports a modular representation of the Plutus Core AST that is divided into three types: +The `PlutusCore.TermF` module exports a modular representation of the Plutus Core and PlutusIR AST that is divided into the following types: - `TermF` which represents abstract syntax that is shared between typed and untyped Plutus Core. - `UntypedF` which represents abstract syntax that is exclusive to untyped Plutus Core. - `TypedF` which represents abstract syntax that is exclusive to typed Plutus Core. +- `PlutusIRF` which represents abstract syntax that is exclusive to PlutusIR. -The abstract syntax of typed and untyped Plutus Core can then be recovered by taking the sum of these functors. In other words, `Sum (TermF ...) (UntypedF ...)` represents the abstract syntax of untyped Plutus Core. We export two type synonyms: +The abstract syntax of typed and untyped Plutus Core as well as PlutusIR can then be recovered by taking the sum of these functors. For example, `Sum (TermF ...) (UntypedF ...)` represents the abstract syntax of Untyped Plutus Core. We export the following type synonyms: - `UntypedTermF` which represents the abstract syntax of untyped Plutus Core. - `TypedTermF` which represents the abstract syntax of typed Plutus Core. +- `PlutusIRTermF` which represents the abstract syntax of PlutusIR. -To convert from the ordinary Plutus Core AST to this module representation, we have the following two functions: +To convert from the ordinary Plutus Core or PlutusIR AST to this modular representation, we have the following functions: - `convertUPLC` converts an untyped Plutus Core `Term` to a representation using `UntypedTermF`. - `convertPLC` converts a typed Plutus Core `Term` to a representation using `TypedTermF`. +- `convertPIR` converts a PlutusIR `Term` to a representation using `PlutusIRTermF`. The modular representation allows us to interweave additional types of nodes into either AST. For example, if we wanted to extend the abstract syntax of untyped Plutus Core with `let`-bindings, we could simply implement the following extension to the abstract syntax: diff --git a/src/PlutusCore/TermF.hs b/src/PlutusCore/TermF.hs index 5b39c0c..2cd5290 100644 --- a/src/PlutusCore/TermF.hs +++ b/src/PlutusCore/TermF.hs @@ -15,22 +15,28 @@ module PlutusCore.TermF ( -- | * Typed terms TypedF(..), TypedTermF, - convertPLC + convertPLC, + -- | * Plutus IR + PlutusIRF(..), + PlutusIRTermF, + convertPIR ) where ------------------------------------------------------------------------------- import Data.ByteString (ByteString) +import Data.List.NonEmpty (NonEmpty) import Data.Fix import Data.Functor.Sum import Data.Text (Text) +import Data.Proxy import PlutusCore.Core qualified as PLC import PlutusCore.Data (Data) import PlutusCore.Default +import PlutusIR.Core qualified as PIR import UntypedPlutusCore qualified as UPLC -import Data.Proxy ------------------------------------------------------------------------------- @@ -156,3 +162,42 @@ convertPLC (PLC.IWrap ann ty0 ty1 term) = Fix $ InR $ IWrap ann ty0 ty1 (convertPLC term) ------------------------------------------------------------------------------- + +-- | Represents terms exclusive to PlutusIR. +data PlutusIRF tyname name ann r + = Let ann PIR.Recursivity (NonEmpty (PIR.Binding tyname name DefaultUni DefaultFun ann)) r + +-- | Represents terms of PLutusIR. +type PlutusIRTermF tyname name const ann = + Sum (TypedTermF tyname name const ann) (PlutusIRF tyname name ann) + +-- | `convertPIR` @term@ converts a PlutusIR @term@ to an equivalent +-- representation that is the sum of `TypedTermF` and `PlutusIRF`. +convertPIR + :: PIR.Term tyname name DefaultUni DefaultFun ann + -> Fix (PlutusIRTermF tyname name DefaultConstant ann) +convertPIR (PIR.Let ann r b t) = Fix $ InR $ Let ann r b (convertPIR t) +-- PIR does not just embed the TPLC terms, but instead re-defines them; +-- there is the `lowerTerm` function in `PlutusIR.Compiler.Lower`, but this +-- is a hidden module, so we have no good way of just reusing `convertPLC` +-- here and instead need to re-define it all +convertPIR (PIR.Var ann name) = Fix $ InL $ InL $ Var (Nothing, ann) name +convertPIR (PIR.LamAbs ann name ty body) = + Fix $ InL $ InL $ LamAbs (Just ty, ann) name (convertPIR body) +convertPIR (PIR.Apply ann fun arg) = + Fix $ InL $ InL $ Apply (Nothing, ann) (convertPIR fun) (convertPIR arg) +convertPIR (PIR.Builtin ann fun) = Fix $ InL $ InL $ Builtin (Nothing, ann) fun +convertPIR (PIR.Constant ann (Some (ValueOf tag x))) = + Fix $ InL $ InL $ Constant (Nothing, ann) $ + bring (Proxy :: Proxy Constant) tag (constant x) +convertPIR (PIR.Error ann ty) = Fix $ InL $ InL $ Error (Just ty, ann) +convertPIR (PIR.TyAbs ann ty k term) = + Fix $ InL $ InR $ TyAbs ann ty k (convertPIR term) +convertPIR (PIR.TyInst ann term ty) = + Fix $ InL $ InR $ TyInst ann (convertPIR term) ty +convertPIR (PIR.Unwrap ann term) = + Fix $ InL $ InR $ Unwrap ann (convertPIR term) +convertPIR (PIR.IWrap ann ty0 ty1 term) = + Fix $ InL $ InR $ IWrap ann ty0 ty1 (convertPIR term) + +-------------------------------------------------------------------------------