Skip to content

Commit

Permalink
Extend modular term representatino with PlutusIR
Browse files Browse the repository at this point in the history
  • Loading branch information
mbg committed Jan 14, 2022
1 parent bb8cc93 commit 01413d0
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
49 changes: 47 additions & 2 deletions src/PlutusCore/TermF.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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

-------------------------------------------------------------------------------

Expand Down Expand Up @@ -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)

-------------------------------------------------------------------------------

0 comments on commit 01413d0

Please sign in to comment.