scalus.uplc.transform
Members list
Type members
Classlikes
Replace nested Apply with Case/Constr
Replace nested Apply with Case/Constr
For example, replace (apply (apply (apply f a) b) c) with (case (constr 0 [a, b, c]) f). This is more memory/cpu efficient than nested Apply at least in Plutus V3 Plomin HF, protocol version 10.
With current machine costs, Apply costs 100 memory and 16000 cpu, same for Case/Constr. Hence (case (constr 0 [a, b, c]) f) costs 200 memory and 32000 cpu, while (apply (apply (apply f a) b) c) costs 300 memory and 48000 cpu.
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CaseConstrApply.type
Extract forced builtins to top level
Extract forced builtins to top level
For example, replace (force (force (builtin fstPair))) with (lam builtin_FstPair (builtin_FstPair (pair true false)) (! (! __builtin_FstPair))). This is more memory/cpu efficient than nested Force at least in Plutus V3 Plomin HF, protocol version 10.
With current machine costs, Force costs 100 memory and 16000 cpu, same for Builtin. Hence (lam builtin_FstPair (builtin_FstPair (pair true false)) (! (! __builtin_FstPair))) costs 200 memory and 32000 cpu, while (force (force (builtin fstPair))) costs 300 memory and 48000 cpu.
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
Optimizes if-then-else expressions by converting lazy branches to strict evaluation when safe.
Optimizes if-then-else expressions by converting lazy branches to strict evaluation when safe.
==Background==
UPLC (Untyped Plutus Core) uses strict evaluation: all function arguments are evaluated before the function is applied. However, for conditional expressions using IfThenElse, we need lazy evaluation to avoid evaluating both branches.
The standard compilation generates:
Force(Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Delay(thenBranch)), Delay(elseBranch)))
This pattern has a cost:
- 2
Delaynodes to suspend branch evaluation - 1
Forcenode to evaluate the selected branch - Total: '''3 extra term node evaluations per if-then-else'''
==The Optimization==
When both branches are "simple values" that evaluate to exactly 1 term, we can safely evaluate them strictly, removing the Delay/Force overhead:
Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), thenBranch), elseBranch)
This saves 3 term node evaluations, improving performance without changing semantics.
==Simple Values (Single-Term Evaluation)==
A term is considered "simple" if it evaluates to exactly 1 term:
Var: Variable lookup (1 term)Const: Constant value (1 term)LamAbs: Lambda abstraction - not executed until applied (1 term)Builtin: Builtin function reference - not executed until applied (1 term)Delay: Suspended computation - not executed (1 term)Constr(_, Nil): Empty constructor (1 term)
Terms that are NOT simple (multi-term evaluation):
Apply: Requires evaluating function + argument (3+ terms)Force: Requires evaluating the forced term (2+ terms)Case: Requires evaluating scrutinee + pattern matching (2+ terms)Constr(_, args)with args: Requires evaluating each argument (1 + n terms)Error: Will fail immediately
==Example==
// Original: if condition then 42 else 100
Force(Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Delay(Const(42))), Delay(Const(100))))
// Cost: 5 term evaluations (Force + Apply + Apply + Apply + Force + 2 Delay + selected Const)
// Optimized: both branches are constants (simple values)
Apply(Apply(Apply(Force(Builtin(IfThenElse)), condition), Const(42)), Const(100))
// Cost: 2 term evaluations (Force + Apply + Apply + Apply + selected Const)
// Savings: 3 term evaluations (2 Delay + 1 Force)
Attributes
- See also
-
scalus.uplc.transform.EtaReduce for another UPLC optimization
scalus.uplc.transform.Inliner for beta-reduction and dead code elimination
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
StrictIf.type
Static analysis utilities for UPLC terms.
Static analysis utilities for UPLC terms.
Provides analysis methods for determining properties of UPLC terms that are useful for optimization and transformation passes.
Attributes
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
TermAnalysis.type