@@ -253,7 +253,6 @@ Here’s an application of `map` and how it rewrites to optimized code:
253253 ys
254254 }
255255
256-
257256### Relationship with Inline and Macros
258257
259258Seen by itself, symmetric meta-programming looks more like a
@@ -399,6 +398,36 @@ to `T` but only `~` is subject to the PCP, whereas `run` is just a normal method
399398 def run: T // run staged code
400399 }
401400
401+ ### Limitations to Splicing
402+
403+ Quotes and splices are duals as far as the PCP is concerned. But there is an additional
404+ restriction that needs to be imposed on splices to guarantee soundness:
405+ code in splices must be free of side effects. The restriction prevents code like this:
406+
407+ var x: Expr[T]
408+ ’{ (y: T) => ~{ x = ’(y); 1 } }
409+
410+ This code, if it was accepted, would "extrude" a reference to a quoted variable ` y ` from its scope.
411+ This means we an subsequently access a variable outside the scope where it is defined, which is
412+ likely problematic. The code is clearly phase consistent, so we cannot use PCP to
413+ rule it out. Instead we postulate a future effect system that can guarantee that splices
414+ are pure. In the absence of such a system we simply demand that spliced expressions are
415+ pure by convention, and allow for undefined compiler behavior if they are not. This is analogous
416+ to the status of pattern guards in Scala, which are also required, but not verified, to be pure.
417+
418+ There is also a problem with ` run ` in splices. Consider the following expression:
419+
420+ ’{ (x: Int) => ~{ {’(x)}.run; 1 } }
421+
422+ This is again phase correct, but will lead us into trouble. Indeed, evaluating the splice will reduce the
423+ expression ` {’(x)}.run ` to ` x ` . But then the result
424+
425+ ’{ (x: Int) => ~{ x; 1 } }
426+
427+ is no longer phase correct. To prevent this soundness hole it seems easiest to classify ` run ` as a side-effecting
428+ operation. It would thus be prevented from appearing in splices. In a base language with side-effects we'd have to
429+ do this anyway: Since ` run ` runs arbitrary code it can always produce a side effect if the code it runs produces one.
430+
402431### The ` Liftable ` type-class
403432
404433Consider the following implementation of a staged interpreter that implements
@@ -615,14 +644,6 @@ splice evaluation context `e_s` are defined syntactically as follows:
615644 Eval context e ::= [ ] | e t | v e | ’e_s[~e]
616645 Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | q e_s
617646
618- A _ run_ operation can be added to the calculus by adding a binding
619- ` run : expr T -> T ` to the initial environment, together with the evaluation rule
620-
621- run('t) --> t
622-
623- That is, ` run ` reduces in the same way as ` ~ ` when in evaluation position. But unlike splices,
624- ` run ` operations are only evaluated outside of quotes, which means they are not affected by the PCP.
625-
626647### Typing rules
627648
628649Typing judgments are of the form ` Es |- t: T ` . There are two
0 commit comments