Immagino che molti implementatori di compilatori per linguaggi imperativi tipici non conoscessero semplicemente le tecniche di compilazione basate su CPS e CPS. Nella comunità di programmazione funzionale sia la compilazione basata su CPS che quella basata su CPS sono tecniche molto conosciute, quest'ultima dal lavoro di Guy Steele. Tuttavia, anche nella comunità FP, la maggior parte dei compilatori non utilizza tecniche basate su CPS per la compilazione a meno che il linguaggio stesso non supporti operatori di controllo come call/cc
. Viene utilizzato qualcosa di più simile al modulo normale amministrativo (ANF) (a volte indicato anche come modulo normale monadico che è intimamente correlato per ragioni che risulteranno chiare) che ha una relazione ancora più stretta con SSA rispetto a CPS .
Se ricordo bene, il modulo amministrativo normale prende il nome dal fatto che la compilazione basata su CPS può portare a beta-redexes nel codice intermedio che non corrispondono a nulla nel codice sorgente. Questi sono stati denominati "redexes amministrativi". Questi potrebbero ridursi in fase di compilazione, ma c'era una buona quantità di ricerca sull'esecuzione di una trasformazione CPS che avrebbe prodotto il codice senza i redexes amministrativi in primo luogo. L'obiettivo era quindi quello di produrre output in una forma normale in cui tutti i redex "amministrativi" erano ridotti e questa era l'origine della forma normale amministrativa. Non ci è voluto molto tempo per rendersi conto che non ci sono stati molti vantaggi nel vederlo come un (n ottimizzazione di un) processo in due fasi: trasformazione CPS, riduzione dei redexes amministrativi. In particolare, la forma normale amministrativa assomiglia piuttosto allo stile monadico praticato (a mano) in particolare a Haskell. La trasformazione CPS può essere intesa come una conversione in stile monadico in cui ti capita di usare la monade CPS (quindi ci sono davvero molti modi per "convertire" in stile monadico corrispondente a diversi ordini di valutazione). In generale, tuttavia, potresti usare una monade abbastanza diversa, quindi la conversione in stile monadico e quindi in una forma normale amministrativa non è in realtà correlata al CPS in particolare.
Tuttavia, ci sono stati alcuni vantaggi in CPS rispetto a ANF. In particolare, c'erano alcune ottimizzazioni che potevi fare in CPS con solo ottimizzazioni standard, come la riduzione beta, che richiedevano (apparentemente) regole ad hoc per ANF. Dal punto di vista monadico, queste regole corrispondono alle conversioni pendolari. Il risultato è che ora esiste una teoria che può spiegare quali regole dovrebbero essere aggiunte e perché. Un recente articolo fornisce una (nuova e) descrizione abbastanza chiara di ciò (da una prospettiva logica) e la relativa sezione di lavoro funge da breve ma decente indagine e riferimenti alla letteratura sugli argomenti che menziono.
Il problema con CPS è legato a uno dei suoi principali vantaggi. La trasformazione CPS consente di implementare operatori di controllo come call/cc
, ma ciò significa che ogni chiamata di funzione non locale nel codice intermedio CPS deve essere trattata come effetti di controllo potenzialmente performanti. Se la tua lingua include operatori di controllo, allora è esattamente come dovrebbe essere (sebbene anche allora la maggior parte delle funzioni probabilmente non eseguono shenanigans di controllo). Se la tua lingua non include gli operatori di controllo, allora ci sono invarianti globali sull'uso di continuazioni che non sono evidenti localmente. Ciò significa che ci sono ottimizzazioni che non sono corrette da eseguire sul codice CPS generale e che sarebbe opportuno eseguire su questo uso particolarmente ben educato del CPS. In questo modo si manifestail cambiamento nella precisione dei dati e le analisi del flusso di controllo . (La trasformazione del CPS aiuta in qualche modo, fa male in altri, anche se i modi in cui aiuta sono principalmente dovuti alla duplicazione piuttosto che all'aspetto CPS stesso.) 1 Naturalmente, è possibile aggiungere regole e regolare le analisi per compensare ciò (vale a dire sfruttare gli invarianti globali), ma poi hai parzialmente sconfitto uno dei maggiori vantaggi della compilazione basata su CPS, ovvero che molte (apparentemente) ottimizzazioni ad hoc per scopi speciali diventano casi speciali di ottimizzazione per scopi generali (in particolare riduzione beta ).
In definitiva, a meno che la tua lingua non disponga di operatori di controllo, di solito non vi sono molte ragioni per utilizzare uno schema di compilazione basato su CPS. Una volta che hai compensato per i problemi che ho menzionato sopra, in genere hai eliminato i vantaggi della compilazione basata su CPS e prodotto qualcosa di equivalente al non utilizzo di CPS. A quel punto, CPS sta solo realizzando un codice intermedio dall'aspetto contorto per non molto beneficio. Un argomento per la compilazione basata su CPS del 2007 affronta alcuni di questi problemi e presenta altri vantaggi utilizzando una diversa forma di conversione CPS. Le cose che la carta riporta sono in parte coperte dal documento (2017) che ho menzionato prima.
1 L'equivalenza tra SSA e CPS non rende questo più o meno impossibile? No. Una delle prime cose che il documento che introduce questa equivalenza afferma è che l'equivalenza non funziona per il codice CPS arbitrario , ma funziona per l'output di una trasformazione CPS (che definiscono) per un linguaggio senza operatori di controllo.