A small Haskell library which contains types and functions for working with Plutus Core, which may be useful across different projects. The library currently offers the following:
- A modular representation of the typed and untyped Plutus Core abstract syntax.
- Smart constructors for constructing untyped Plutus Core terms, e.g. for writing tests.
- Helper functions for parsing/serialising typed/untyped Plutus Core programs.
Before you can use this library, add it as a dependency in your stack.yaml
extra-deps:
- git: [email protected]:HachiSecurity/plc-utils
commit: a6fbc2eb9fbef5fd48d14bf69faab5c1743da61aor cabal.project
source-repository-package
type: git
location: [email protected]:HachiSecurity/plc-utils
tag: a6fbc2eb9fbef5fd48d14bf69faab5c1743da61aThen add it as a dependency to your .cabal or package.yaml.
To generate the documentation for this library, run e.g. stack haddock.
The PlutusCore.TermF module exports a modular representation of the Plutus Core and PlutusIR AST that is divided into the following types:
TermFwhich represents abstract syntax that is shared between typed and untyped Plutus Core.UntypedFwhich represents abstract syntax that is exclusive to untyped Plutus Core.TypedFwhich represents abstract syntax that is exclusive to typed Plutus Core.PlutusIRFwhich represents abstract syntax that is exclusive to PlutusIR.
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:
UntypedTermFwhich represents the abstract syntax of untyped Plutus Core.TypedTermFwhich represents the abstract syntax of typed Plutus Core.PlutusIRTermFwhich represents the abstract syntax of PlutusIR.
To convert from the ordinary Plutus Core or PlutusIR AST to this modular representation, we have the following functions:
convertUPLCconverts an untyped Plutus CoreTermto a representation usingUntypedTermF.convertPLCconverts a typed Plutus CoreTermto a representation usingTypedTermF.convertPIRconverts a PlutusIRTermto a representation usingPlutusIRTermF.
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:
data LetTermF name r
= Let name r r
deriving (Eq, Show, Functor)
type UntypedLetTermF name const ann =
Sum (UntypedTermF name const ann) (LetTermF name)As a short example of how this might be used, consider a function which attempts to turn all function applications into let-bindings:
restoreLets
:: Fix (UntypedTermF name DefaultConstant ann)
-> Fix (UntypedLetTermF name DefaultConstant ann)
restoreLets (Fix (InL (Apply _ (Fix (InL (LamAbs _ name body))) arg))) =
Fix $ InR $ Let name (restoreLets body) (restoreLets arg)
restoreLets (Fix term) = Fix $ InL $ fmap restoreLets term