Τρίτη, 5 Φεβρουαρίου 2019

Αναθεώρηση 11, Έκδοση 9.7 (Τελική)


Σε αυτήν την αναθεώρηση διορθώθηκε ο χρωματιστής εντολών (επαναφορά μιας λειτουργίας που "χάλασε" λόγω αλλαγής συμπεριφοράς μιας συνάρτησης, η λύση ήταν να βγεί μια άλλη τοπική ώστε να δουλεύει όπως είχε σχεδιαστεί)
πχ στο παρακάτω πρόγραμμα (Y Combinator) οι δυο πρώτες γιραμμές με την Print δεν εμφανίζονταν σωστά στον διοθρωτή. Υπάρχει το F11 για αυτές τις περιπτώσεις όπου αφαιρεί άμεσα το χρώμα, και η εμφάνιση επανέρχεται σωστά. Αλλά τώρα που έχει διορθωθεί, δεν υπάρχει θέμα χρήσης "αποχρωματισμού". Ο διορθωτής δεν φυλάει το χρώμα, δηλαδή όποτε ανοίγουμε ένα τμήμα να το διορθώσουμε το χρωματίζει άμεσα. Επίσης δουλεύει καθώς πληκτρολογούμε. Από την έκδοση 9.8 (είναι ακόμα στις αρχές της), ο χρωματιστής θα παίξει το ρόλο του lexical analyzer. Σκοπεύω να αλλάξω τον τρόπο εκτέλεσης. Τώρα ο μεταφραστής είναι ένα σύνολο συναρτήσεεων που καλούν η μια την άλλη, και παρέχουν τον κώδικα που η κάθε μια θα εκτελέσει σε μορφή αλφαριθμητικού. Κάθε φορά πχ που υπάρχει ένας αριθμός στο κώδικα, πχ το 10 θα πρέπει να κληθεί η συνάρτηση που από το κώδικα θα επιστρέψει το 10.  Με βόλεψε αυτή η κατάσταση για να φτιάξω το πρότυπο της γλώσσας. Τώρα έχει ολοκληρωθεί και έτσι το επόμενο βήμα θα είναι η σύσταση του λεγόμενου AST ώστε να έχουμε έναν AST Interpreter, όπου θα έχει ολοκληρωθεί το lexical analyzer και το syntax analyzer.

Το Abstract syntax tree (AST),  περιλαμβάνει κόμβους (Nodes) εκ των οποίων κάποιοι θα είναι τελικοί (leaf), πχ ένα αλφαριθμητικό, ή ένας αριθμός.

Ο χρωματιστής δίνει τις συναρτήσεις του για να φτιαχτεί το lexical analyzer. Στο τέλος το συντακτικό δένδρο, θα είναι αυτό που θα εκετελείται. Το δένδρο αυτό σου λέει ποια θα είναι η επόμενη εντολή και έχει όλες τις λφαριθμητικές παραστάσεις σε μορφή άμεσης εκτέλεσης χωρίς παρένθεση, δηλαδή το 2+3 θα είναι ως 2 3 +, ή βάλε 2, βάλε 3, Πρόσθεσε.
Δεν θα είναι εύκολη η υπόθεση γιατί πρέπει να υλοποιηθούν όλες οι ιδιαιτερότητες της Μ2000, όπως τα άλματα (GOTO) τα οποία σημαίνουν συνδέσεις μεταξύ των κόμβων του δένδρου. Ήδη υπάρχει προεργασία, πχ και τώρα όταν καλεί ο διερμηνευτής πχ την Print βρίσκει από ένα πίνακα κατακερματισμού σε χρόνο Ο(1) την διεύθυνση της συνάρτησης και την καλεί. Με αυτόν τον τρόπο καταργήθηκε ένα αρχικό μεγάλο Select Case, όπου σήμαινε ότι η τελευταία στη λίστα θα εκτελούνταν αφού πρώτα γίνονταν συγκρισεις σε κάθε άλλο μέλος της λίστας. Ο πίνακας κατακερματισμού δίνει με έναν τύπο (τη συνάρτηση κατακερματισμού) τη θέση του κλειδιού που ψάχνουμε, εδώ το αναγνωριστικό. Στην νέα έκδοση 9.αυτός ο πίνακας θα χρησιμοποιείται πάλι, αλλά τώρα δεν θα έχει το όνομα να ψάχνει αλλά έναν ακέραιο αριθμό (ακόμα πιο γρήγορα). Ο πίνακας των εντολών έχει δυνατότητα να αυξομειώνεται, ώστε εντολές όπως η Print ή Τύπωσε να μπορούν να αναπρογραμματιστούν, κατά την εκτέλεση. Έτσι το AST θα περιέχει τον κωδικό της Print, αλλά αν δεν έρθει η ώρα της εκτέλεσης δεν θα ξέρει  επακριβώς τι πρέπει να καλέσει, Αυτό θα συμβαίνει συνεχώς και για άλλους τύπους, όπως πχ μια λάμδα συνάρτηση, η οποία δεν ξέρει ποια είναι (επειδή οι λάμδα συναρτήσεις ειναι σαν μεταβλητές, μπορούν να δώσουν τον εαυτό τους ως τιμή και να πάρουν ως τιμή μια άλλη λάμδα, σημαίνει ότι κάπου στις μεταβλητές θα υπάρχει ένας δείκτης σε ένα Ast δένδρο, με όλες τις αναφορές έμμεσε, ώστε το ίδιο δένδρο να δουλεύει ταυτόχρονα για πολλές συναρτήσεις. Πχ μια τέτοια περίπτωση είναι η Y combinator. Αυτός λοιπόν παίρνει μια συνάρτηση και αποδίδει μια άλλη συνάρτηση ενώ έχει κάνει την αρχική ως τύπου αναδρομής. Ενώ δηλαδή η συνάρτηση δεν καλεί τον εαυτό της, εντέλει καλεί συναρτήσεις που είναι όπως ο εαυτός της, επειδή ο combinator την παρέχει. Υπάρχουν δυο τρόποι υλοποίησης. Ο πρώτος εμφανίζεται στις δυο πρώτες Τύπωσε ή Print. έχουμε μια δυο παραμέτρους g και x και εκτελείται το g(g,x), δείτε ότι η πρώτη παράμετρος είναι με τιμή πέρασμα της g (στην Μ2000 το πέρασμα με αναφορά γίνεται με το &, ενώ σε μεταβλητές που είναι δείκτες σε αντικείμενα, ακόμα και το πέρασμα με τιμή είναι εν μέρη πέρασμα με αναφορά, απλά δεν μπορεί να αλλάξει δείκτη προς το αντικείμενο από την πλευρά της κλήσης). Οι λάμδα συναρτήσεις αν περαστούν με τιμή, τότε δίνουν αντίγραφο του εαυτού τους, που σημαίνει ότι τα τυχόν κλεισίματα (closures) θα αντιγραφούν, θα περαστούν με τιμή δηλαδή.

Δείτε ότι αμέσως μετά τη δήλωση της ανώνυμης συνάρτησης δίνουμε τις δυο παραμέτρους, η πρώτη είναι η ανώνυμη που δίνει το επόμενο παραγοντικό, και η δεύτερη έναν αριθμό που ουσιασικιά παίζει τον αριθμό εκτέλεσης, έτσι το δέκα θα εκτελέσει διαδοχικά δέκα φορές, δέκα αντίγραφα της αρχικής συνάρτησης και θα πάρουμε το δέκατο παραγοντικό. Η επόμενη είναι η ακολουθία fibonacci

Ο δεύτερο τρόπος παράγει μια λάμδα που κρατάει μια δεύτερη τον Y combinator. Η πρώτη δηλαδή απλά παίρνει έναν αριθμό, και περιέχει ως κλείσιμο τον Y combinator, και έτσι δεν χρειάζεται να το παρέχουμε σε κάθε κλήση.

Στη Μ2000 στις συναρτήσεις που καλούμε σε παραστάσεις δεν υπάρχει κοινό όνομα χώρου, ή αλλιώς οι μεταβλητές/συναρτήσις έξω από τη συνάρτηση είναι αθέατες, εκτός και αν οριστούν ως γενικές. Η διαθεσιμότητα των γενικών παύει όταν αυτό που τις δημιούργησε τερματίσει. Επίσης αν καλέσουμε μια συνάρτηση και ορίσουμε μια τοπική με ίδιο όνομα με γενική τότε η τελευταία θα είναι σκιασμένη, δεν θα μπορεί να χρησιμοποιηθεί στο κώδικα, μεχρι να τερματίσει. η συνάρτηση.
Αυτά για την ώρα. Αν βρεθεί κάποιο λάθος στην 9.7 θα διορθωθεί, αλλά πρακτικά σταματάει η αναβάθμισή της. Το νέο εγχειρίδιο στα αγγλικά γράφεται, το μικρό στα ελληνικά εμπλουτίζεται.. Το μεγάλο στα ελληνικά είναι σε αυτό το τόπο, σε κοινή θέα.



Module Ycombinator {
      \\ factorial
      Print lambda (gx)->{=g(gx)}(lambda (gn)->if(n=0->1, n*g(gn-1)),10)
       \\ fibonacci
      Print lambda (gx)->{=g(gx)}(lambda (gn)->if(n<=1->n,g(gn-1)+g(gn-2)), 10)

      \\ Using closure in y, y() return function
      y=lambda (g)->lambda (x-> g(gx)
   
      fact=y((lambda (gn)-> if(n=0->1, n*g(gn-1))))
      Print fact(6)fact(24)
   
      fib=y(lambda (gn)->if(n<=1->n,g(gn-1)+g(gn-2)))
      Print fib(10)
}
Ycombinator

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου