Quali sono i motivi per scegliere una rappresentazione AST omogenea o eterogenea per l'implementazione di un linguaggio di programmazione complesso specifico per il dominio?
Per essere molto chiari su ciò che sto chiedendo, ecco qualche altro background:
Per omogeneo, intendo un albero costituito da nodi che sono un singolo tipo generico . Per esempio, penso che questa domanda sia realmente indipendente dal linguaggio, ma usando una struct di tipo C ++ per l'illustrazione, considererei questo un nodo di sintassi astratto omogeneo e minimale:
struct Node {
int tag;
void *data;
Node *first_child;
Node *next_sibling;
};
Per eterogeneo, intendo un albero costituito da nodi che sono singoli tipi multipli (ad esempio uno per ogni produzione di grammatica). Per esempio, non voglio assumere un particolare linguaggio, ma usando ancora le strutture simili a C ++ per l'illustrazione, considererei questi tipi parte di una gerarchia usata per costruire un albero di sintassi astratto eterogeneo:
struct Node {};
struct Integer_Node : Node {
int value;
};
struct Plus_Node : Node {
Node *right;
Node *left;
};
struct If_Statement : Node {
Node *Condition;
Node *Then_Expression;
Node *Else_Expression;
};
// ... more types, depending on the language ...
Nel corso degli anni, ho implementato diversi piccoli compilatori speciali, di solito in un modo molto specifico. Non ho mai usato un vero "AST" perché solitamente la traduzione diretta della sintassi è stata abbastanza buona.
Ora sono in procinto di progettare e implementare un nuovo linguaggio molto più complesso, dove costruirò un AST e poi lo passerò sopra con più passaggi per la verifica, l'analisi semantica e così via.
Ad esempio, sembra che l'uso di uno schema omogeneo riduca la quantità di codice in anticipo, ma mi chiedo se un sistema eterogeneo si ripaga meglio a lungo termine per ragioni che non sto considerando. D'altra parte, lo schema eterogeneo sembra che possa trarre beneficio dal controllo di tipo statico del compilatore, dalla distribuzione del metodo virtuale, ecc., Ma mi chiedo se una cosa del genere sia davvero molto utile nello sviluppo di passaggi semantici e così via.
Fondamentalmente, spero di ottenere alcune informazioni da coloro che potrebbero avere qualche esperienza reale qui. Ho letto molti libri di compilatori e ho una discreta quantità di esperienza di scrittura di compilatori di base, ma non ho visto questa particolare dicotomia affrontata in nessuna letteratura che riesco a mettere le mani su.