@@ -253,7 +253,6 @@ Here’s an application of `map` and how it rewrites to optimized code:
253
253
ys
254
254
}
255
255
256
-
257
256
### Relationship with Inline and Macros
258
257
259
258
Seen 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
399
398
def run: T // run staged code
400
399
}
401
400
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
+
402
431
### The ` Liftable ` type-class
403
432
404
433
Consider the following implementation of a staged interpreter that implements
@@ -615,14 +644,6 @@ splice evaluation context `e_s` are defined syntactically as follows:
615
644
Eval context e ::= [ ] | e t | v e | ’e_s[~e]
616
645
Splice context e_s ::= [ ] | (x: T) => e_s | e_s t | q e_s
617
646
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
-
626
647
### Typing rules
627
648
628
649
Typing judgments are of the form ` Es |- t: T ` . There are two
0 commit comments