3

Für die Codegenerierung in meiner Programmiersprache benutze ich das Besuchermuster und ich möchte einen besseren Weg finden, um Zuweisungsanweisungen zu handhaben.Besucher Muster und Compiler-Code-Generierung, wie die Zuordnung zu bearbeiten?

Meine virtuelle Maschine basiert registriert und jeder Ausdruck Knoten besuchten nur eine Registernummer zu einem globalen Stack PUSH so, wenn ich den binären Ausdruck Knoten besuchen ich einen Code wie ausführen:

static void visit_binary_expr (gvisitor_t *self, gnode_binary_expr_t *node) { 
    DECLARE_CODE(); 

    bool is_assignment = (node->op == TOK_OP_ASSIGN); 
    if (is_assignment) { 
     // assignment is right associative 
     visit(node->right); 
     visit(node->left); 
    } else { 
     // visiting binary operation from left to right 
     visit(node->left); 
     visit(node->right); 
    } 

    if (!is_assignment) { 
     uint32_t r3 = ircode_register_pop(code); 
     uint32_t r2 = ircode_register_pop(code); 
     uint32_t r1 = ircode_register_push_temp(code); 

     opcode_t op = token2opcode(node->op); 
     ircode_add(code, op, r1, r2, r3); 
    } 
} 

Mit diesem Code kann ich Prozessanweisungen wie: a + b Variable a in Register 1 und die Variable b in dem Register 2-Code erzeugt Angenommen wird:

ADD 3 1 2 

Das Problem besteht darin, dass Zuweisungen einen anderen Satz von Anweisungen erforderlich ist und auf ly Registerzahlen auf dem Stapel ist nicht ausreichend. Um beispielsweise auf eine globale Variable zuzugreifen (lesen) zu können, sollte ich eine GLOAD-Anweisung verwenden, während zum Speichern (Schreiben) in eine globale Variable ich eine GSTORE-Anweisung verwenden sollte.

Ich löse das Problem derzeit, indem ich einen booleschen is_assignment-Wert in jedem Knoten hinterlege, damit ich rekursiv prüfen kann, welche Anweisung generiert werden soll, aber das viel Logik in jedem besuchten Knoten erfordert und ich möchte wirklich herausfinden eleganterer Weg, bei dem nur die Funktion visit_binary_expr entscheiden kann, welche die beste zu erzeugende Anweisung ist.

Antwort

1

Da sich die Zuweisung von anderen binären Operationen unterscheidet (es hat einen Nebeneffekt, einen linken Operanden zu ändern), ist es sinnvoll, sie als eine vollständig separate Operation zu verarbeiten, die überhaupt nicht mit den binären Operationen in Beziehung steht . In diesem Fall hätten Sie etwas wie visit_assignment mit dem zweiten Argument des entsprechenden Typs.

Dann könnten Sie alle Prüfungen vermeiden, die im aktuellen Code vorhanden sind. Abhängig von den Zieltypen, die Ihre Sprache erlaubt, kann die Verarbeitung des Zuweisungsziels auch einen anderen Satz von Traversierungsfunktionen, einen anderen Besucher oder denselben Besucher mit einem Flag verwenden, das anzeigt, dass ein Ziel verarbeitet wird, und nicht ein regulärer Ausdruck . Die Entscheidung, welcher Ansatz besser ist, hängt von der Sprache und dem Code ab, den Sie generieren müssen.