Παρασκευή, 29 Ιουνίου 2018

Revision 17 (Version 9.3) - Visitor Patern

Σε αυτή την αναθεώρηση έκανα μια προσθήκη στους δείκτες για ομάδες ώστε να μπορεί να λειτουργήσει και το παράδειγμα Visitor Pattern.
Το Visitor Pattern, εδώ κάνει την όλη δουλειά στο who.a.accept &this. Αυτό που αλλάζει είναι το a, που μπορεί να είναι literal ή Add, όπου και τα δύο έχουν την accept. Η accept προκαλεί την κλήση πάλι της visitor, στο αρχικό Parser, αλλά γίνεται έλεγχος του τύπου του αντικειμένου. Η Μ2000 δεν έχει τύπους στις ομάδες (όλα είναι ένας τύπος), αλλά μπορούμε να βάλουμε μια μεταβλητή και αυτή να δηλώνει τον τύπο, με έλεγχο που κάνουμε με την Valid() ή Έγκυρο().

Κάθε φορά λοιπόν που θέλει να "προβληθεί" (εδώ να γραφτεί στο  sb$  αλφαριθμητικό) ένα από τις δυο κλάσεις μας, θα καλέσει την visit και θα δώσει μια αναφορά σε αυτό, ώστε να υπάρχει τρόπος να πάρουμε περισσότερα στοιχεία. Έτσι η parser θα πάρει την τιμή του n και θα την γράψει στο sb$, αν η visit κλήθηκε από το accept της literal.

Πριν την προσθήκη λειτουργούσε μόνο με αναφορές:

Πρόγραμμα με χρήση αναφορών



Class literal {
      Iamliteral
      n
      module literal (.n) {}
      module accept(&visitor) {
            visitor.visit &this
      }
}
Class Add {
      Group a
      Group b
      module Add (.a, .b) {}
      module accept( &visitor) {
      visitor.visit &this
      }
}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
      sb$
      module visit (&who) {
            If valid(who.Iamliteral) then {
                 .sb$<=.sb$+Str$(who.n,"")
            } else {
                  .sb$<=.sb$+"("
                  who.a.accept &this
                  .sb$<=.sb$+"+"
                  who.b.accept &this
                  .sb$<=.sb$+")"
            }
      }
}
Parser.Visit &M
Print Parser.sb$


Δίνει αυτό:
((100+200)+((100+200)+50))

Τώρα το ίδιο πρόγραμμα με χρήση δεικτών. Αυτό που δεν μπορούσε να γίνει στις προηγούμενες αναθεωρήσεις ήταν το m->This, ενώ το m->(This) μπορούσε να γίνει, αλλά βγαίνει δείκτης σε αντίγραφο του This (Αυτό). Επειδή οι κλάσεις επιστρέφουν ομάδα (χωρίς δείκτη), έχουμε δυο συναρτήσεις που γυρίζουν δείκτες (αντί για = έχουν το -> για επιστροφή τιμής).

Στο who=>a=>accept m έχουμε δυο δείκτες, το whο και το a, οπότε για να βρούμε το a δίνουμε το who=>a, και μετά επειδή ζητάμε το visit του a δίνουμε ξανά το =>visit m,  ή όλο μαζί who=>a=>visit m


Class literal1 {
      Iamliteral
      n
      module literal1 (.n) {}
      module accept(visitor) {
            m->this
            visitor=>visit m
      }
}
Class Add1 {
      Group a
      Group b
      module Add1 (.a, .b) {}
      module accept( visitor) {
      m->this
      visitor=>visit m
      }
}
Function Literal(a) {->literal1(a)}
Function Add(a, b) {->Add1(a, b)}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
      sb$
      module visit (who) {
            If valid(who=>Iamliteral) then {
                 .sb$<=.sb$+Str$(who=>n,"")
            } else {
                  m->This
                  .sb$<=.sb$+"("
                  who=>a=>accept m
                  .sb$<=.sb$+"+"
                  who=>b=>accept m
                  .sb$<=.sb$+")"
            }
      }
}
Parser.Visit M
Print Parser.sb$