Δηλωτική σημασιολογία
Στην επιστήμη των υπολογιστών, η δηλωτική σημασιολογία (denotational semantics) είναι μια προσέγγιση για την τυποποίηση της σημασίας των γλωσσών προγραμματισμού μέσω της κατασκευής μαθηματικών αντικειμένων (που ονομάζονται δηλώσεις, denotations), τα οποία περιγράφουν τις σημασίες των εκφράσεων των γλωσσών.
Άλλες προσεγγίσεις της τυπικής σημασιολογίας των γλωσσών προγραμματισμού είναι η αξιωματική σημασιολογία (axiomatic semantics) και η λειτουργική σημασιολογία (operational semantics).
Η δηλωτική σημασιολογία, γενικά, ασχολείται με την εύρεση μαθηματικών αντικειμένων που ονομάζονται πεδία (domains), που αναπαριστούν αυτό που κάνει ένα πρόγραμμα.
Για παράδειγμα, κάποια προγράμματα (ή φράσεις από προγράμματα) μπορούν να αναπαρασταθούν από μερικές συναρτήσεις, από σενάρια διαγραμμάτων συμβάντων από Actors ή από παίγνια (games) μεταξύ του περιβάλλοντος και του συστήματος: όλα αυτά είναι γενικά παραδείγματα πεδίων.
Μια σημαντική αρχή της δηλωτικής σημασιολογίας είναι ότι η σημασιολογία πρέπει να είναι συνθετική: η σημασιολογία μιας φράσης του προγράμματος πρέπει να κατασκευάζεται από τις δηλώσεις των υποφράσεών της.
Ανάπτυξη της δηλωτικής σημασιολογίας
Η δηλωτική σημασιολογία προήλθε από το έργο του Christopher Strachey και του Dana Scott κατά τη δεκαετία του 1960.
Όπως αρχικά αναπτύχθηκε από αυτούς, η δηλωτική σημασιολογία έδινε τη δήλωση (σημασία) ενός προγράμματος υπολογιστή ως μια συνάρτηση που αντιστοιχίζει είσοδο σε έξοδο.
Για να δοθούν οι δηλώσεις των αναδρομικά ορισμένων προγραμμάτων, ο Scott πρότεινε την εργασία με συνεχείς συναρτήσεις μεταξύ πεδίων, και ειδικότερα πλήρεις σχέσεις μερικής διάταξης (complete partial orders).
Όπως θα περιγραφεί στη συνέχεια, το έργο αυτό συνεχίστηκε προς την έρευνα πάνω στην κατάλληλη δηλωτική σημασιολογία που αφορά πλευρές των γλωσσών προγραμματισμού, όπως η αλληλουχίες εντολών (sequentiality), ο ταυτοχρονισμός, ο μη-ντετερμινισμός και η τοπική κατάσταση (local state).
Έχουν αναπτυχθεί δηλωτικές σημασιολογίες για σύγχρονες γλώσσες προγραμματισμού που χρησιμοποιούν capabilities όπως ο ταυτοχρονισμός και οι εξαιρέσεις, π.χ. η ActorScript, η Concurrent ML, οι CSP, και η Haskell.
Οι σημασιολογίες αυτών των γλωσσών υπακούουν στον κανόνα της σύνθεσης γιατί η δήλωση μιας φράσης εξαρτάται από τις δηλώσεις των υποφράσεών της.
Για παράδειγμα, η σημασία της έκφρασης f(E1,E2) ορίζεται με βάση τη σημασιολογία των υποφράσεών της f, E1 και E2.
Σε μια σύγχρονη γλώσσα προγραμματισμού, οι E1 και E2 μπορούν να αποτιμώνται ταυτόχρονα και η εκτέλεσης της μιας από αυτές μπορεί να επηρεάζει την άλλη μέσω κοινών αντικειμένων, με αποτέλεσμα οι σημασιολογία τους να πρέπει να ορίζεται αμοιβαία.
Επίσης η E1 ή η E2 μπορεί να προκαλέσουν μια εξαίρεση, η οποία προκαλεί τον τερματισμό της άλλης.
Οι παρακάτω ενότητες περιγράφουν ειδικές περιπτώσεις της σημασιολογίας αυτών των σύγχρονων γλωσσών προγραμματισμού.
Η δηλωτική σημασιολογία αντιστοιχίζει σε κάθε φράση προγράμματος μια συνάρτηση από ένα περιβάλλον (που περιέχει τις τιμές των ελεύθερων μεταβλητών της) στη δήλωσή της.
Για παράδειγμα, η φράση n*m παράγει μια δήλωση όταν της δοθεί ένα περιβάλλον που έχει δεσμεύσεις για τις δύο μεταβλητές της: τη n και τη m.
Αν στο περιβάλλον η n έχει την τιμή 3 και η m έχει την τιμή 5, τότε η δήλωση είναι 15.
Μια συνάρτηση μπορεί να μοντελοποιηθεί ως ένα σύνολο από διατεταγμένα ζεύγη, με κάθε ζεύγος να αποτελείται από δύο μέρη: (1) ένα όρισμα για τη συνάρτηση και (2) την τιμή της συνάρτησης για αυτό το όρισμα.
Για παράδειγμα, το σύνολο των διατεταγμένων ζευγών {[0 1] [4 3]} είναι η δήλωση μιας συνάρτησης με τιμή 1 για όρισμα 0, τιμή 3 για όρισμα 4, και μη ορισμένη σε κάθε άλλη περίπτωση.
Το πρόβλημα που πρέπει να λυθεί είναι η απόδοση δηλώσεων σε αναδρομικά προγράμματα που ορίζονται με βάση τον εαυτό τους, όπως ο ορισμός της συνάρτησης παραγοντικό (factorial):
:factorial ≡ λ(n) if (n==0) then 1 else n*factorial(n-1).
Μια λύση είναι η κατασκευή της δήλωσης προσεγγιστικά, αρχίζοντας με το κενό σύνολο διατεταγμένων ζευγών (το οποίο στη θεωρία συνόλων θα μπορούσε να γραφεί ως {}).
Αν το {} τοποθετηθεί στον παραπάνω ορισμό του παραγοντικού τότε η δήλωση είναι {[0 1]}, που είναι μια καλύτερη προσέγγιση του παραγοντικού.
Επαναληπτικά: αν το {[0 1]} τοποθετηθεί στον ορισμό τότε η δήλωση είναι {[0 1] [1 1]}.
Επομένως είναι βολικό μια προσέγγιση της factorial να θεωρείται ως μία είσοδος F ως εξής:
:λ(F) λ(n) if (n==0) then 1 else n*F(n-1).
Είναι χρήσιμο να θεωρηθεί μια αλυσίδα από "επαναλήψεις" όπου η Fi αντιστοιχεί σε i-φορές εφαρμογή της F.
Το ελάχιστο άνω όριο (least upper bound) αυτής της αλυσίδας είναι η πλήρης συνάρτηση factorial, η οποία μπορεί να εκφραστεί ως εξής, με το σύμβολο "⊔" να σημαίνει "ελάχιστο άνω όριο":
:⊔i∈NFi({})
Η έννοια των power domains αναπτύχθηκε για δοθεί μια δηλωτική σημασιολογία των μη ντετερμινιστικών ακολουθιακών προγραμμάτων.
Αν P είναι ένας κατασκευαστης power domain, το P(D) είναι το πεδίο των μη ντετερμινιστικών υπολογισμών με τύπο που δηλώνεται από το D.
Υπάρχουν κάποιες δυσκολίες όσον αφορά τη δικαιοσύνη (fairness) και τις μη φραγμένες συμπεριφορές σε πεδιο-θεωρητικά μοντέλα του μη ντετερμινισμού.
Δείτε επίσης Power domains.
Αρκετοί ερευνητές θεωρούν ότι τα πεδιο-θεωρητικά μοντέλα που δόθηκαν παραπάνω δεν αρκούν για τη γενική περίπτωση του ταυτόχρονου υπολογισμού.
Για αυτόν το λόγο έχουν προταθεί διάφορα νέα μοντέλα.
Στις αρχές του 1980, το στυλ της δηλωτικής σημασιολογίας άρχισε να χρησιμοποιείται για την απόδοση σημασιολογίας σε γλώσσες ταυτοχρονισμού.
Παραδείγματα είναι η δουλειά του Will Clinger στο μοντέλο Actor, η δουλειά του Glynn Winskel σε δομές συμβάντων (event structures) και δίκτυα petri , και η δουλειά των Francez, Hoare, Lehmann, και de Roever (1979) στα trace semantics για CSP.
Αυτές οι κατευθύνσεις της έρευνας συνεχίζουν να προχωρούν.
Πρόσφατα, ο Winskel και άλλοι πρότειναν την κατηγορία των profunctors ως θεωρία πεδίων για τον ταυτοχρονισμό.
Η κατάσταση (όπως ο σωρός) και απλά χαρακτηριστικά των προστακτικών γλωσσών προγραμματισμού μπορούν να μοντελοποιηθούν με ευθύ τρόπο στη δηλωτική σημασιολογία που προαναφέρθηκε.
Τα βιβλία περιέχουν περισσότερες πληροφορίες.
Η βασική ιδέα είναι η θεώρηση μιας εντολής σαν μιας μερικής συνάρτησης σε κάποιο πεδίο από καταστάσεις.
Τότε η δήλωση του "x:=3" είναι η συνάρτηση που από μια κατάσταση σε μια κατάσταση με την τιμή 3 να έχει ανατεθεί στην x.
Ο τελεστής ακολουθιών εντολών ";" δηλώνεται με σύνθεση συναρτήσεων.
Οι κατασκευές σταθερού σημείου χρησιμοποιούνται στη συνέχεια για να δώσουν σημασιολογία στους βρόχους, όπως στην εντολή "while".
Η μοντελοποίηση προγραμμάτων με τοπικές μεταβλητές είναι δυσκολότερη.
Μια προσέγγιση είναι να μη χρησιμοποιούνται πια πεδία, αλλά να ερμηνεύονται οι τύποι ως functors από κάποια κατηγορία από κόσμους σε μια κατηγορία από πεδία.
Οι δηλώσεις τότε των προγραμμάτων προκύπτουν από φυσικός μετασχηματισμός φυσικές συνεχείς συναρτήσεις ανάμεσα σε αυτούς τους functors.
Πολλές γλώσσες προγραμματισμού επιτρέπουν στο χρήστη να ορίζει αναδρομικούς τύπους δεδομένων.
Για παράδειγμα, ο τύπος των λιστών αριθμών μπορεί να οριστεί ως:
:datatype list = Cons of (Nat, list) | Empty.
Αυτή η ενότητα ασχολείται μόνο με συναρτησιακές δομές δεδομένων που δεν αλλάζουν.
Οι συμβατικές προστακτικές γλώσσες προγραμματισμού θα επέτρεπαν στα στοιχεία μιας τέτοιας αναδρομικής λίστας να αλλάζουν.
Ένα άλλο παράδειγμα: ο τύπος των δηλώσεων του λ-λογισμού χωρίς τύπους είναι:
:datatype D = (D → D)
Το πρόβλημα της επίλυσης εξισώσεων πεδίων ασχολείται με την εύρεση πεδίων που μοντελοποιούν τέτοιους τύπους δεδομένων.
Γενικά μιλώντας, μια προσέγγιση είναι να θεωρείται το σύνολο όλων των πεδίο ως πεδίο, και στη συνέχεια να επιλύεται εκεί ο αναδρομικός ορισμός.
Τα βιβλία περιέχουν περισσότερες πληροφορίες.
Οι πολυμορφικοί τύποι δεδομένων είναι τύποι δεδομένων που ορίζονται με μια παράμετρο.
Για παράδειγμα, ο τύπος των λιστών από α (α lists) ορίζεται ως εξής:
:datatype α list = Cons of (α, list) | Empty.
Οι λίστες από αριθμούς είναι τότε τύπου Nat list, ενώ οι λίστες από συμβολοσειρές είναι String list.
Έχουν αναπτυχθεί κάποια πεδιο-θεωρητικά μοντέλα του πολυμορφισμού από κάποιους ερευνητές, ενώ κάποιοι άλλοι έχουν μοντελοποιήσει τον παραμετρικό πολυμορφισμό σε κατασκευαστικές θεωρίες συνόλων.
Περισσότερες λεπτομέρειες μπορούν να βρεθούν στα βιβλία.
Πρόσφατα υπάρχει ένα πεδίο έρευνας για δηλωτική σημασιολογία για γλώσσες προγραμματισμού που βασίζονται σε κλάσεις ή αντικείμενα.
Λόγω της ανάπτυξης γλωσσών προγραμματισμού βασισμένων στη γραμμική λογική, έχει αποδοθεί δηλωτική σημασιολογία σε γλώσσες που περιλαμβάνουν γραμμική χρήση (π...χ proof nets, coherence spaces) και πολυπλοκότητα πολυωνυμικού χρόνου.
Το πρόβλημα της αφαίρεσης για την ακολουθιακή γλώσσα προγραμματισμού PCF αποτέλεσε για μεγάλο χρονικό διάστημα, ένα μεγάλο ανοιχτό ερώτημα της δηλωτικής σημασιολογίας.
Το πρόβλημα της PCF είναι ότι είναι πολύ ακολουθιακή ως γλώσσα.
Για παράδειγμα, δεν υπάρχει τρόπος να οριστεί η συνάρτηση παράλληλη-διάζευξη (parallel-or) στην PCF.
Για αυτόν το λόγο, η παραπάνω τεχνική με τη χρήση πεδίων, έχει ως αποτέλεσμα δηλωτική σημασιολογία που δεν είναι πλήρως αφηρημένη.
Αυτό το ανοιχτό ερώτημα απαντήθηκε σε μεγάλο βαθμό κατά τη δεκαετία του 1990 με την ανάπτυξη των game semantics και με τεχνικές που περιλάμβαναν λογικές σχέσεις.
Για περισσότερες λεπτομέρειες, βλ.
PCF.
Συχνά είναι χρήσιμο να μεταφράζεται μια γλώσσα προγραμματισμού σε μια άλλη.
Για παράδειγμα, μια ταυτόχρονη γλώσσα προγραμματισμού θα μπορούσε να μεταφραστεί σε λογισμό διεργασιών (process calculus) ενώ μια γλώσσα προγραμματισμού υψηλού επιπέδου θα μπορούσε να μεταφραστεί σε κώδικα byte (byte-code).
Η κλασική δηλωτική σημασιολογία μπορεί να θεωρηθεί ως η ερμηνεία γλωσσών προγραμματισμού ως η εσωτερική γλώσσα της κατηγορίας των πεδίων.
Σε αυτά τα πλαίσια, οι ιδέες της δηλωτικής σημασιολογίας, όπως η πλήρης αφαίρεση, βοηθούν στην ικανοποίηση απαιτήσεων ασφαλείας.
Αφαίρεση
Συχνά θεωρείται σημαντικό να συνδέεται η δηλωτική σημασιολογία με τη λειτουργική σημασιολογία.
Αυτό είναι ιδιαίτερα σημαντικό όταν η δηλωτική σημασιολογία είναι πολύ μαθηματική και αφηρημένη, και η λειτουργική σημασιολογία είναι πιο στέρεη ή πιο κοντά σε υπολογιστικές έννοιες.
Οι παρακάτω ιδιότητες της δηλωτικής σημασιολογίες πολλές φορές θεωρούνται ενδιαφέρουσες.
Επιπλέον επιθυμητές ιδιότητες ανάμεσα στη λειτουργική και τη δηλωτική σημασιολογία είναι:
Αρχή της σύνθεσης
Ένα σημαντικό χαρακτηριστικό της δηλωτικής σημασιολογίας είναι η Αρχή της σύνθεσης (compositionality), σύμφωνα με την οποία η δήλωση ενός προγράμματος κατασκευάζεται από τις δηλώσεις των τμημάτων του.
Για παράδειγμα, έστω η έκφραση "7 + 4".
Η αρχή της σύνθεσης σε αυτήν την περίπτωση είναι το να δοθεί σημασία στην "7 + 4" με όρους "7", "4" και "+".
Η βασική δηλωτική σημασιολογία της θεωρίας πεδίων είναι συνθετική γιατί δίνεται όπως περιγράφεται στη συνέχεια.
Αρχίζουμε θεωρώντας αποσπάσματα προγράμματος, δηλαδή προγράμματα με ελεύθερες μεταβλητές.
Ένα περιβάλλον τυποποίησης (typing context) δίνει κάποιον τύπο σε κάθε ελεύθερη μεταβλητή.
Για παράδειγμα, η έκφραση (x + y) θα μπορούσε να θεωρηθεί σε ένα περιβάλλον τυποποίησης (x:nat,y:nat).
Στη συνέχεια δίνουμε δηλωτική σημασιολογία στα αποσπάσματα του προγράμματος, ακολουθώντας το εξής σχέδιο.
Με αυτόν τον τρόπο, η σημασία της σύνθετης έκφρασης (7+4) ορίζεται από τη σύνθεση των τριών συναρτήσεων 〚⊢7:nat〛:1→ℕ⊥, 〚⊢4:nat〛:1→ℕ⊥, και 〚x:nat,y:nat⊢x+y:nat〛:ℕ⊥×ℕ⊥→ℕ⊥.
Τα παραπάνω αποτελούν ένα γενικότερο σχήμα για τη συνθετική δηλωτική σημασιολογία.
Δεν υπάρχει κάτι που να αφορά ιδιαίτερα τα πεδία και τις συνεχείς συναρτήσεις.
Κάποιος θα μπορούσε να δουλέψει αντί αυτών, με μια διαφορετική κατηγορία.
Για παράδειγμα, στα game semantics, η κατηγορία των παιγνίων έχει τα παίγνια ως αντικείμενα και τις στρατηγικές ως μορφισμούς: μπορούμε να ερμηνεύσουμε τους τύπους ως παίγνια και τα προγράμματα ως στρατηγικές.
Σε μια απλή γλώσσα, χωρίς γενική αναδρομή, μπορούμε να χρησιμοποιήσουμε την κατηγορία των συνόλων.
Σε μια γλώσσα με παρενέργειες, μπορούμε να εργαστούμε με την κατηγορία Kleisliγια μια μονάδα.
Σε μια γλώσσα με κατάσταση, μπορούμε να εργαστούμε με μια κατηγορία functor.
Ο Robin Milner έχει υποστηρίξει τη μοντελοποίηση της θέσης (location) και της αλληλεπίδρασης (interaction) με την εργασία σε μια κατηγορία με αντικείμενα interfaces και μορφισμούς bigraphs.
Σημασιολογία και υλοποίηση
Σύμφωνα με το Dana Scott [1980]:
Δε χρειάζεται η σημασιολογία να ορίζει την υλοποίηση, αλλά θα πρέπει να παρέχει κριτήρια που δείχνουν ότι μια υλοποίηση είναι σωστή.
Σύμφωνα με τον Clinger [1981]:
Συνήθως, όμως, η τυπική σημασιολογία μιας κλασικής ακολουθιακής γλώσσας προγραμματισμού μπορεί να διερμηνευτεί η ίδια ώστε να αποτελέσει μια (μη αποδοτική) υλοποίηση της γλώσσας.
Όμως η τυπική σημασιολογία δε χρειάζεται πάντα να παρέχει μια τέτοια υλοποίηση, και η πίστη ότι η σημασιολογία πρέπει να δίνει μια υλοποίηση οδηγεί σε σύγχυση όσον αφορά την τυπική σημασιολογία των ταυτόχρονων γλωσσών.
Αυτή η σύγχυση είναι δυστυχώς εμφανής όταν η εμφάνιση του μη ντετερμινισμού χωρίς φράγμα στη σημασιολογία μιας γλώσσας προγραμματισμού λέμε ότι υπονοεί ότι η γλώσσα προγραμματισμού δε μπορεί να υλοποιηθεί.
Συνδέσεις με άλλες περιοχές της επιστήμης υπολογιστών
Υπάρχει έργο στη δηλωτική σημασιολογία που ερμηνεύει τους τύπους ως πεδία όπως η θεωρία πεδίων (domain theory), η οποία μπορεί να θεωρηθεί παρακλάδι της θεωρίας μοντέλων (model theory), οδηγώντας στη θεωρία τύπων και στη θεωρία κατηγοριών.
Μέσα στην επιστήμη των υπολογιστών, υπάρχουν σχέσεις με την αφηρημένη διερμηνεία, την τυπική επαλήθευση (formal verification) και τον έλεγχο μοντέλων.
Οι μονάδες (monads) εισήχθηκαν στη δηλωτική σημασιολογία για την οργάνωση της σημασιολογίας, και οι ιδέες αυτές έχουν προκαλέσει σημαντικό αντίκτυπο στο συναρτησιακό προγραμματισμό.
Περαιτέρω διάβασμα
