G-machine, (un) strict contexts - why case expressions require special treatment

I am currently reading Implementing Functional Languages: a tutorial on the SPJ and (sub) chapter, which I will refer to in this issue, is 3.8.7 (p. 136).

The first observation is that the reader following the tutorial has not yet implemented a compilation of C schema (i.e., expressions appearing in non-strict contexts) of ECase expressions.
The proposed solution is to transform the main program, so ECase expressions simply do not appear in non-standard contexts. In particular, each such occurrence creates a new super-combinator with exactly one variable, whose body corresponds to the original ECase expression, and the entry itself is replaced by a call to this super-combinator.
Below I present a (slightly modified) example of such a conversion from 1

tab = Pack{2,1} ; fx = Pack{2,2} (case tx 7 6 of <1> -> 1; <2> -> 2) Pack{1,0} ; main = f 3 == transformed into ==> tab = Pack{2,1} ; fx = Pack{2,2} ($Case1 (tx 7 6)) Pack{1,0} ; $Case1 x = case x of <1> -> 1; <2> -> 2 ; main = f 3 

I implemented this solution, and it works like a charm, that is, the output is Pack{2,2} 2 Pack{1,0} .
However, I do not understand why all these problems? I hope this is not only me, but the first thought I decided to solve was to simply compile ECase expressions in Schema C. And I did this by imitating the rule for compilation in Schema E (p. 134 in 1 but I present this rule here for completeness): therefore I used

 E[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p] 

and wrote

 C[[case e of alts]] p = C[[e]] p ++ [Eval] ++ [Casejump D[[alts]] p] 

I added [Eval] because Casejump needs an argument over the stack in normal normal weak head form (WHNF), and the C scheme does not guarantee that, unlike the E scheme.

But then the output changes to the mysterious: Pack{2,2} 2 6 .
The same applies when I use the same rule as for scheme E, i.e.

 C[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p] 

Therefore, I assume that my β€œobvious” decision is inherently wrong - and I see this from the results. But I am having problems with formal arguments as to why this approach will inevitably fail.
Could someone provide me with such an argument / proof or some intuition as to why the naive approach doesn't work?

+6
source share
1 answer

The purpose of Scheme C is to not perform any calculations, but simply to postpone everything until EVAL happens (which may or may not). What do you do in the proposed code generation for case ? You are calling EVAL! And the whole purpose of C is to not call EVAL anything, so you already rated something prematurely.

The only way we could generate the code directly for case in Schema C would be to add a new statement to analyze the case after evaluating it.

But we (Thomas Johnsson and I) decided it was easier to simply remove such expressions. However, accurate historical data is lost. :)

+7
source

Source: https://habr.com/ru/post/980324/


All Articles