-
Notifications
You must be signed in to change notification settings - Fork 463
/
PlutusCore.hs
237 lines (220 loc) · 6.23 KB
/
PlutusCore.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
-- Why is it needed here, but not in "Universe.Core"?
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# OPTIONS_GHC -Wno-deferred-out-of-scope-variables #-}
module PlutusCore
(
-- * Parser
parseProgram
, parseTerm
, parseType
, parseScoped
-- * Builtins
, Some (..)
, SomeTypeIn (..)
, Kinded (..)
, ValueOf (..)
, someValueOf
, someValue
, Esc
, Contains (..)
, Includes
, Closed (..)
, EverywhereAll
, knownUniOf
, GShow (..)
, show
, GEq (..)
, deriveGEq
, HasUniApply (..)
, checkStar
, withApplicable
, (:~:) (..)
, type (<:)
, DefaultUni (..)
, pattern DefaultUniList
, pattern DefaultUniPair
, DefaultFun (..)
-- * AST
, Term (..)
, termSubterms
, termSubtypes
, UniOf
, Type (..)
, typeSubtypes
, Kind (..)
, ParseError (..)
, Version (..)
, Program (..)
, Name (..)
, TyName (..)
, Unique (..)
, UniqueMap (..)
, Normalized (..)
, defaultVersion
, toTerm
, termAnn
, typeAnn
, tyVarDeclAnn
, tyVarDeclName
, tyVarDeclKind
, varDeclAnn
, varDeclName
, varDeclType
, tyDeclAnn
, tyDeclType
, tyDeclKind
, mapFun
-- * DeBruijn representation
, DeBruijn (..)
, NamedDeBruijn (..)
, deBruijnProgram
, deBruijnTerm
, unDeBruijnProgram
, unDeBruijnTerm
-- * Lexer
, SourcePos
-- * Formatting
, format
, formatDoc
-- * Processing
, HasUniques
, Rename (..)
-- * Type checking
, module TypeCheck
, fileType
, fileTypeCfg
, printType
, normalizeTypesIn
, normalizeTypesInProgram
, AsTypeError (..)
, TypeError
, parseTypecheck
-- for testing
, typecheckPipeline
-- * Errors
, Error (..)
, AsError (..)
, NormCheckError (..)
, AsNormCheckError (..)
, UniqueError (..)
, AsUniqueError (..)
, FreeVariableError (..)
, AsFreeVariableError (..)
-- * Base functors
, TermF (..)
, TypeF (..)
-- * Quotation and term construction
, Quote
, runQuote
, QuoteT
, runQuoteT
, MonadQuote
, liftQuote
-- * Name generation
, freshUnique
, freshName
, freshTyName
-- * Evaluation
, EvaluationResult (..)
-- * Combining programs
, applyProgram
-- * Benchmarking
, termSize
, typeSize
, kindSize
, programSize
, serialisedSize
-- * Budgeting defaults
, defaultBuiltinCostModel
, defaultBuiltinsRuntime
, defaultCekCostModel
, defaultCekMachineCosts
, defaultCekParameters
, defaultCostModelParams
, unitCekParameters
-- * CEK machine costs
, cekMachineCostsPrefix
, CekMachineCosts (..)
) where
import PlutusPrelude
import PlutusCore.Check.Uniques qualified as Uniques
import PlutusCore.Core
import PlutusCore.DeBruijn
import PlutusCore.Default
import PlutusCore.Error
import PlutusCore.Evaluation.Machine.Ck
import PlutusCore.Evaluation.Machine.ExBudgetingDefaults
import PlutusCore.Flat ()
import PlutusCore.Name
import PlutusCore.Normalize
import PlutusCore.Parser
import PlutusCore.Pretty
import PlutusCore.Quote
import PlutusCore.Rename
import PlutusCore.Size
import PlutusCore.TypeCheck as TypeCheck
import UntypedPlutusCore.Evaluation.Machine.Cek.CekMachineCosts
import Control.Monad.Except
import Data.ByteString.Lazy qualified as BSL
import Data.Text qualified as T
import Text.Megaparsec (ParseErrorBundle, SourcePos, errorBundlePretty, initialPos)
topSourcePos :: SourcePos
topSourcePos = initialPos "top"
-- | Given a file at @fibonacci.plc@, @fileType "fibonacci.plc"@ will display
-- its type or an error message.
fileType :: FilePath -> IO T.Text
fileType = fmap (either (T.pack . errorBundlePretty) id . printType) . BSL.readFile
-- | Given a file, display
-- its type or an error message, optionally dumping annotations and debug
-- information.
fileTypeCfg :: FilePath -> IO T.Text
fileTypeCfg = fmap (either (T.pack . errorBundlePretty) id . printType) . BSL.readFile
-- | Print the type of a program contained in a 'ByteString'
printType
:: BSL.ByteString
-> Either (ParseErrorBundle T.Text ParseError) T.Text
printType bs = T.pack . show . pretty <$> do
scoped <- parseScoped bs
config <- getDefTypeCheckConfig topSourcePos
inferTypeOfProgram config scoped
-- | Parse and rewrite so that names are globally unique, not just unique within
-- their scope.
parseScoped
:: BSL.ByteString
-> Either (ParseErrorBundle T.Text ParseError) (Program TyName Name DefaultUni DefaultFun SourcePos)
-- don't require there to be no free variables at this point, we might be parsing an open term
parseScoped = through (Uniques.checkProgram (const True)) <=< rename <=< parseProgram
-- | Parse a program and typecheck it.
parseTypecheck
:: TypeCheckConfig DefaultUni DefaultFun
-> BSL.ByteString
-> Either (ParseErrorBundle T.Text ParseError) (Normalized (Type TyName DefaultUni ()))
parseTypecheck cfg = typecheckPipeline cfg <=< parseScoped
-- | Typecheck a program.
typecheckPipeline
:: (AsTypeError e (Term TyName Name DefaultUni DefaultFun ()) DefaultUni DefaultFun a,
MonadError e m,
MonadQuote m)
=> TypeCheckConfig DefaultUni DefaultFun
-> Program TyName Name DefaultUni DefaultFun a
-> m (Normalized (Type TyName DefaultUni ()))
typecheckPipeline = inferTypeOfProgram
formatDoc ::
PrettyConfigPlc -> BSL.ByteString ->
Either (ParseErrorBundle T.Text ParseError) (Doc a)
-- don't use parseScoped since we don't bother running sanity checks when we format
formatDoc cfg = fmap (prettyBy cfg) . (rename <=< parseProgram)
format
:: PrettyConfigPlc -> BSL.ByteString ->
Either (ParseErrorBundle T.Text ParseError) T.Text
-- don't use parseScoped since we don't bother running sanity checks when we format
format cfg = fmap (displayBy cfg) . (rename <=< parseProgram)
-- | Take one PLC program and apply it to another.
applyProgram
:: Monoid a
=> Program tyname name uni fun a
-> Program tyname name uni fun a
-> Program tyname name uni fun a
applyProgram (Program a1 _ t1) (Program a2 _ t2) = Program (a1 <> a2) (defaultVersion mempty) (Apply mempty t1 t2)