Skip to content

Commit 97c1471

Browse files
committed
Fix the steppable machine, add the 'fixLoop' test
1 parent 23775ab commit 97c1471

File tree

21 files changed

+86
-46
lines changed

21 files changed

+86
-46
lines changed

plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/Exception.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ data MachineError fun
6363
| NonConstrScrutinized
6464
| MissingCaseBranch Word64
6565
| NonLambdaFixedMachineError
66+
| FixLoopMachineError
6667
deriving stock (Show, Eq, Functor, Generic)
6768
deriving anyclass (NFData)
6869

@@ -136,3 +137,5 @@ instance (HasPrettyDefaults config ~ 'True, Pretty fun) =>
136137
"Case expression missing the branch required by the scrutinee tag:" <+> pretty i
137138
prettyBy _ NonLambdaFixedMachineError =
138139
"Attempted to take the fixed-point of a non-lambda term"
140+
prettyBy _ FixLoopMachineError =
141+
"Fix entered infinite recursion"

plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/Cek/Internal.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ dischargeCekValEnv valEnv = go 0
511511
-- var is in the env, discharge its value
512512
(\case
513513
VBlackHole recName recLamCnt ->
514+
-- TODO: is this right?
514515
Var () (NamedDeBruijn recName . coerce $ lamCnt - recLamCnt)
515516
val -> dischargeCekValue val)
516517
-- index relative to (as seen from the point of view of) the environment
@@ -541,7 +542,8 @@ dischargeCekValue = \case
541542
stack2list = go []
542543
go acc EmptyStack = acc
543544
go acc (ConsStack arg rest) = go (arg : acc) rest
544-
VBlackHole _ _ -> error "can't happen"
545+
-- TODO: is this right?
546+
VBlackHole recName _ -> Var () (NamedDeBruijn recName 0)
545547

546548
instance (PrettyUni uni, Pretty fun) => PrettyBy PrettyConfigPlc (CekValue uni fun ann) where
547549
prettyBy cfg = prettyBy cfg . dischargeCekValue
@@ -772,6 +774,7 @@ enterComputeCek = computeCek
772774
let env' = Env.contUpdateZero (\_ -> bodyV') env (Env.length env - recIx)
773775
bodyV' = VLamAbs nameArg bodyLam env'
774776
returnCek ctx bodyV'
777+
VBlackHole{} -> throwingDischarged _MachineError FixLoopMachineError bodyV
775778
_ -> throwingDischarged _MachineError NonLambdaFixedMachineError bodyV
776779

777780
-- | Evaluate a 'HeadSpine' by pushing the arguments (if any) onto the stack and proceeding with

plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/SteppableCek/Internal.hs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import Control.Monad
5959
import Control.Monad.Primitive
6060
import Data.Proxy
6161
import Data.RandomAccessList.Class qualified as Env
62+
import Data.RandomAccessList.SkewBinary qualified as Env
6263
import Data.Semigroup (stimes)
6364
import Data.Text (Text)
6465
import Data.Vector qualified as V
@@ -101,7 +102,7 @@ data Context uni fun ann
101102
| FrameForce ann !(Context uni fun ann) -- ^ @(force _)@
102103
| FrameConstr ann !(CekValEnv uni fun ann) {-# UNPACK #-} !Word64 ![NTerm uni fun ann] !(ArgStack uni fun ann) !(Context uni fun ann)
103104
| FrameCases ann !(CekValEnv uni fun ann) !(V.Vector (NTerm uni fun ann)) !(Context uni fun ann)
104-
| FrameFix ann !(Context uni fun ann)
105+
| FrameFix ann !Word64 !(Context uni fun ann)
105106
| NoFrame
106107

107108
deriving stock instance (GShow uni, Everywhere uni Show, Show fun, Show ann, Closed uni)
@@ -165,9 +166,10 @@ computeCek !ctx !env (Constr ann i es) = do
165166
computeCek !ctx !env (Case ann scrut cs) = do
166167
stepAndMaybeSpend BCase
167168
pure $ Computing (FrameCases ann env cs ctx) env scrut
168-
computeCek !ctx !env (Fix ann _ bodyOuter) = do
169+
computeCek !ctx !env (Fix ann rec body) = do
169170
stepAndMaybeSpend BFix
170-
pure $ Computing (FrameFix ann ctx) env bodyOuter
171+
let !len' = Env.length env + 1
172+
pure $ Computing (FrameFix ann len' ctx) (Env.cons (VBlackHole (ndbnString rec) len') env) body
171173
-- s ; ρ ▻ error A ↦ <> A
172174
computeCek !_ !_ (Error _) =
173175
throwing_ _EvaluationFailure
@@ -216,13 +218,13 @@ returnCek (FrameCases ann env cs ctx) e = case e of
216218
in computeCek ctx' env t
217219
Nothing -> throwingDischarged _MachineError (MissingCaseBranch i) e
218220
_ -> throwingDischarged _MachineError NonConstrScrutinized e
219-
returnCek (FrameFix _ ctx) bodyOuter =
220-
case bodyOuter of
221-
VLamAbs nameArg bodyInner env ->
222-
let env' = Env.cons bodyOuter' env
223-
bodyOuter' = VLamAbs nameArg bodyInner env'
224-
in pure $ Returning ctx bodyOuter'
225-
_ -> throwingDischarged _MachineError NonLambdaFixedMachineError bodyOuter
221+
returnCek (FrameFix _ recIx ctx) bodyV =
222+
case bodyV of
223+
VLamAbs nameArg bodyLam env -> do
224+
let env' = Env.contUpdateZero (\_ -> bodyV') env (Env.length env - recIx)
225+
bodyV' = VLamAbs nameArg bodyLam env'
226+
pure $ Returning ctx bodyV'
227+
_ -> throwingDischarged _MachineError NonLambdaFixedMachineError bodyV
226228

227229
-- | @force@ a term and proceed.
228230
-- If v is a delay then compute the body of v;
@@ -394,7 +396,7 @@ contextAnn = \case
394396
FrameForce ann _ -> pure ann
395397
FrameConstr ann _ _ _ _ _ -> pure ann
396398
FrameCases ann _ _ _ -> pure ann
397-
FrameFix ann _ -> pure ann
399+
FrameFix ann _ _ -> pure ann
398400
NoFrame -> empty
399401

400402
lenContext :: Context uni fun ann -> Word
@@ -408,7 +410,7 @@ lenContext = go 0
408410
FrameForce _ k -> go (n+1) k
409411
FrameConstr _ _ _ _ _ k -> go (n+1) k
410412
FrameCases _ _ _ k -> go (n+1) k
411-
FrameFix _ k -> go (n+1) k
413+
FrameFix _ _ k -> go (n+1) k
412414
NoFrame -> 0
413415

414416

plutus-core/untyped-plutus-core/test/Evaluation/Builtins/Definition.hs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import PlutusCore.Compiler.Erase (eraseTerm)
3333
import PlutusCore.Data
3434
import PlutusCore.Default
3535
import PlutusCore.Evaluation.Machine.ExBudgetingDefaults
36+
import PlutusCore.Evaluation.Machine.Exception
3637
import PlutusCore.Evaluation.Machine.MachineParameters
3738
import PlutusCore.Examples.Builtins
3839
import PlutusCore.Examples.Data.Data
@@ -524,6 +525,20 @@ test_fixId =
524525
]
525526
typecheckAndEvalToOutOfEx fixId
526527

528+
test_fixLoop :: TestTree
529+
test_fixLoop =
530+
testCase "a 'fix' loop finishes" $ do
531+
let fixLoop :: Term TyName Name DefaultUni DefaultFun ()
532+
fixLoop = runQuote $ do
533+
rec <- freshName "rec"
534+
pure $ Fix () rec (TyFun () integer integer) $ Var () rec
535+
evalRestricting params = fst . runCekNoEmit params restrictingLarge
536+
case typecheckAnd def evalRestricting defaultBuiltinCostModelForTesting fixLoop of
537+
Right (Left (ErrorWithCause (StructuralEvaluationError FixLoopMachineError) _)) ->
538+
pure ()
539+
err ->
540+
assertFailure $ "Expected a 'FixLoopMachineError' but got: " ++ displayPlc err
541+
527542
-- | If the first char is an opening paren and the last chat is a closing paren, then remove them.
528543
-- This is useful for rendering a term-as-a-test-name in CLI, since currently we wrap readably
529544
-- pretty-printed terms in parens (which is to be fixed).
@@ -1212,6 +1227,7 @@ test_definition =
12121227
#endif
12131228
, test_SerialiseDataImpossible
12141229
, test_fixId
1230+
, test_fixLoop
12151231
, runTestNestedHere
12161232
[ test_Integer
12171233
, test_String

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/Fib/1.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
| BStep BBuiltin causes ({cpu: 32000 | mem: 200})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 43837 | mem: 1})
1213
| BBuiltinApp IfThenElse causes ({cpu: 76049 | mem: 1})
1314
| BStartup causes ({cpu: 100 | mem: 100})})
14-
| budget: ({cpu: 583986
15-
| mem: 3002})
15+
| budget: ({cpu: 599986
16+
| mem: 3102})
1617
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/Fib/2.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
| BStep BBuiltin causes ({cpu: 144000 | mem: 900})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp AddInteger causes ({cpu: 101208 | mem: 2})
1213
| BBuiltinApp SubtractInteger causes ({cpu: 202416 | mem: 4})
1314
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 131511 | mem: 3})
1415
| BBuiltinApp IfThenElse causes ({cpu: 228147 | mem: 3})
1516
| BStartup causes ({cpu: 100 | mem: 100})})
16-
| budget: ({cpu: 2215382
17-
| mem: 9812})
17+
| budget: ({cpu: 2231382
18+
| mem: 9912})
1819
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/Fib/3.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
| BStep BBuiltin causes ({cpu: 256000 | mem: 1600})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp AddInteger causes ({cpu: 202416 | mem: 4})
1213
| BBuiltinApp SubtractInteger causes ({cpu: 404832 | mem: 8})
1314
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 219185 | mem: 5})
1415
| BBuiltinApp IfThenElse causes ({cpu: 380245 | mem: 5})
1516
| BStartup causes ({cpu: 100 | mem: 100})})
16-
| budget: ({cpu: 3846778
17-
| mem: 16622})
17+
| budget: ({cpu: 3862778
18+
| mem: 16722})
1819
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IdNat/0.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
| BStep BBuiltin causes ({cpu: 0 | mem: 0})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 16000 | mem: 100})
5455
| BStartup causes ({cpu: 100 | mem: 100})})
55-
| budget: ({cpu: 5168100
56-
| mem: 32400})
56+
| budget: ({cpu: 5184100
57+
| mem: 32500})
5758
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IdNat/3.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 48000 | mem: 300})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 16000 | mem: 100})
5455
| BBuiltinApp Id causes ({cpu: 0 | mem: 0})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 5312100
57-
| mem: 33300})
57+
| budget: ({cpu: 5328100
58+
| mem: 33400})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IdNat/6.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 96000 | mem: 600})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 16000 | mem: 100})
5455
| BBuiltinApp Id causes ({cpu: 0 | mem: 0})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 5456100
57-
| mem: 34200})
57+
| budget: ({cpu: 5472100
58+
| mem: 34300})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IdNat/9.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 144000 | mem: 900})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 16000 | mem: 100})
5455
| BBuiltinApp Id causes ({cpu: 0 | mem: 0})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 5600100
57-
| mem: 35100})
57+
| budget: ({cpu: 5616100
58+
| mem: 35200})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/0.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
| BStep BBuiltin causes ({cpu: 0 | mem: 0})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 16000 | mem: 100})
5455
| BStartup causes ({cpu: 100 | mem: 100})})
55-
| budget: ({cpu: 5168100
56-
| mem: 32400})
56+
| budget: ({cpu: 5184100
57+
| mem: 32500})
5758
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/1.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 16000 | mem: 100})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 32000 | mem: 200})
5455
| BBuiltinApp IfThenElse causes ({cpu: 76049 | mem: 1})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 5740149
57-
| mem: 35501})
57+
| budget: ({cpu: 5772149
58+
| mem: 35701})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/2.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 32000 | mem: 200})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 32000 | mem: 200})
5455
| BBuiltinApp IfThenElse causes ({cpu: 152098 | mem: 2})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 5976198
57-
| mem: 36502})
57+
| budget: ({cpu: 6008198
58+
| mem: 36702})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/3.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 48000 | mem: 300})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 32000 | mem: 200})
5455
| BBuiltinApp IfThenElse causes ({cpu: 228147 | mem: 3})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 6212247
57-
| mem: 37503})
57+
| budget: ({cpu: 6244247
58+
| mem: 37703})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/4.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 64000 | mem: 400})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 32000 | mem: 200})
5455
| BBuiltinApp IfThenElse causes ({cpu: 304196 | mem: 4})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 6448296
57-
| mem: 38504})
57+
| budget: ({cpu: 6480296
58+
| mem: 38704})
5859
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Budget/IfThenElse/5.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
| BStep BBuiltin causes ({cpu: 80000 | mem: 500})
5252
| BStep BConstr causes ({cpu: 0 | mem: 0})
5353
| BStep BCase causes ({cpu: 0 | mem: 0})
54+
| BStep BFix causes ({cpu: 32000 | mem: 200})
5455
| BBuiltinApp IfThenElse causes ({cpu: 380245 | mem: 5})
5556
| BStartup causes ({cpu: 100 | mem: 100})})
56-
| budget: ({cpu: 6684345
57-
| mem: 39505})
57+
| budget: ({cpu: 6716345
58+
| mem: 39705})
5859
}) )
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9
1+
10

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Tallying/Fib/1.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
| BStep BBuiltin causes ({cpu: 32000 | mem: 200})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 43837 | mem: 1})
1213
| BBuiltinApp IfThenElse causes ({cpu: 76049 | mem: 1})
1314
| BStartup causes ({cpu: 100 | mem: 100})})
14-
| budget: ({cpu: 583986
15-
| mem: 3002})
15+
| budget: ({cpu: 599986
16+
| mem: 3102})
1617
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Tallying/Fib/2.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
| BStep BBuiltin causes ({cpu: 144000 | mem: 900})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp AddInteger causes ({cpu: 101208 | mem: 2})
1213
| BBuiltinApp SubtractInteger causes ({cpu: 202416 | mem: 4})
1314
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 131511 | mem: 3})
1415
| BBuiltinApp IfThenElse causes ({cpu: 228147 | mem: 3})
1516
| BStartup causes ({cpu: 100 | mem: 100})})
16-
| budget: ({cpu: 2215382
17-
| mem: 9812})
17+
| budget: ({cpu: 2231382
18+
| mem: 9912})
1819
}) )

plutus-core/untyped-plutus-core/test/Evaluation/Machines/Tallying/Fib/3.uplc.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
| BStep BBuiltin causes ({cpu: 256000 | mem: 1600})
99
| BStep BConstr causes ({cpu: 0 | mem: 0})
1010
| BStep BCase causes ({cpu: 0 | mem: 0})
11+
| BStep BFix causes ({cpu: 16000 | mem: 100})
1112
| BBuiltinApp AddInteger causes ({cpu: 202416 | mem: 4})
1213
| BBuiltinApp SubtractInteger causes ({cpu: 404832 | mem: 8})
1314
| BBuiltinApp LessThanEqualsInteger causes ({cpu: 219185 | mem: 5})
1415
| BBuiltinApp IfThenElse causes ({cpu: 380245 | mem: 5})
1516
| BStartup causes ({cpu: 100 | mem: 100})})
16-
| budget: ({cpu: 3846778
17-
| mem: 16622})
17+
| budget: ({cpu: 3862778
18+
| mem: 16722})
1819
}) )

0 commit comments

Comments
 (0)