DedSec Project

haxe — συγκεντρωτικός οδηγός — DedSec Project

haxe — συγκεντρωτικός οδηγός Haxe Τι εγγυάται η Haxe Η Haxe διαθέτει στατικό έλεγχο τύπων, συμπερασμό τύπων και παραγωγή κώδικα για πολλούς στόχους, μεταξύ τους τη JavaScript. Μπορούμε να…

Haxe

Τι εγγυάται η Haxe

Η Haxe διαθέτει στατικό έλεγχο τύπων, συμπερασμό τύπων και παραγωγή κώδικα για πολλούς στόχους, μεταξύ τους τη JavaScript. Μπορούμε να μοιραστούμε λογική ανάμεσα σε στόχους, όχι όμως να θεωρήσουμε ίδιες όλες τις βιβλιοθήκες, την αναπαράσταση ακεραίων ή τα API του περιβάλλοντος. Κάνουμε ξεχωριστή μεταγλώττιση για κάθε στόχο.

Το παράδειγμα χρησιμοποιεί αλγεβρικό τύπο δεδομένων αντί για ασαφές κενό μήνυμα σφάλματος. Αποθήκευσέ το ως Main.hx:

enum Status {
  Ready;
  Failed(reason:String);
}

class Main {
  static function label(status:Status):String {
    return switch (status) {
      case Ready: "ready";
      case Failed(reason): "failed: " + reason;
    };
  }

  static function main() {
    trace(label(Ready));
    trace(label(Failed("offline")));
  }
}

Εκτέλεσε haxe --main Main --interp ή haxe --main Main --js main.js και έπειτα node main.js. Σημείωσε haxe --version και, για JavaScript, node --version. Οι αναμενόμενες τιμές trace είναι ready και failed: offline, συνήθως μαζί με πληροφορίες αρχείου και γραμμής.

Γιατί έχει σημασία ο enum

Ο Status είναι είτε Ready είτε Failed με αιτία. Το switch επιστρέφει String σε κάθε κλάδο και ο μεταγλωττιστής ελέγχει τα ονόματα των constructors και τους τύπους. Πρόσθεσε τρίτη περίπτωση Pending και επανεξέτασε όλα τα switch ώστε να την καλύπτουν. Η παράλειψη περίπτωσης είναι πρόβλημα πληρότητας κατά τη μεταγλώττιση· δεν το κρύβουμε με αόριστο default. Ένα λάθος όνομα, όπως Fialed, αποτελεί επίσης σφάλμα μεταγλωττιστή.

Το δείγμα χρησιμοποιεί βασικά χαρακτηριστικά της γλώσσας. Πρόσβαση σε αρχεία, DOM browser ή threads μπορεί να χρειάζεται διαφορετικό στόχο και εξαρτήσεις. Κατάγραψε ρητά τα όρια κάθε πλατφόρμας.

Διάγνωση και κριτήρια

Αν δεν εντοπίζεται η Main, έλεγξε ότι το Main.hx βρίσκεται στον σωστό φάκελο και περιέχει class Main. Αν παραχθεί JavaScript αλλά δεν υπάρχει node, έχει ελεγχθεί μόνο η μεταγλώττιση. Αν ο enum δεν εντοπίζεται αφού μετακινηθεί σε άλλο αρχείο, εξέτασε τα module/type names και τις εισαγωγές της Haxe.

Άσκηση 1: πρόσθεσε Pending και κάλυψέ το στο label. Άσκηση 2: υλοποίησε isFailure : Status -> Bool και εξέτασε όλες τις περιπτώσεις. Άσκηση 3: σύγκρινε δύο εγκατεστημένους στόχους με ίδιες εισόδους. Παράδωσε πηγαίο κώδικα, έκδοση μεταγλωττιστή, εντολές, προβλέψεις και πραγματικές παρατηρήσεις. Οι τιμές του κειμένου προκύπτουν από στατική ανάλυση, όχι από ισχυρισμό τοπικής εκτέλεσης Haxe.

Εργαστήριο εξάσκησης: Haxe

Πρόβλημα και όριο εμπιστοσύνης

Ένα πεδίο ρυθμίσεων δικτύου πρέπει να δέχεται μόνο ψηφία ASCII που σχηματίζουν αριθμό θύρας από 1 έως 65535. Η Std.parseInt από μόνη της δεν αποτελεί αυστηρό έλεγχο: η επιτρεπτική μετατροπή αριθμητικού προθέματος μπορεί να δεχτεί αλλοιωμένο κείμενο. Έλεγξε ολόκληρη τη συμβολοσειρά πριν τη μετατροπή. Χρησιμοποίησε συνθετικά δεδομένα· το παράδειγμα δεν ανοίγει συνδέσεις.

Αποθήκευσε ως Main.hx σε προσωρινό φάκελο:

class Main {
  static function parsePort(raw:String):Null<Int> {
    if (raw.length == 0 || raw.length > 5) return null;
    var digits = ~/^[0-9]+$/;
    if (!digits.match(raw) || digits.matched(0).length != raw.length) return null;
    var port = Std.parseInt(raw);
    if (port == null || port < 1 || port > 65535) return null;
    return port;
  }

  static function main() {
    trace(parsePort("8080"));
    trace(parsePort("0"));
    trace(parsePort("12abc"));
    trace(parsePort("00080"));
    trace(parsePort("65536"));
  }
}

Εκτέλεσε haxe --main Main --interp. Προαιρετικά μεταγλώττισε με haxe --main Main --js main.js και εκτέλεσε node main.js. Αναμενόμενες τιμές: 8080, null, null, 80, null. Η trace ενδέχεται να εμφανίσει επιπλέον όνομα αρχείου και γραμμή.

Αιτιολόγηση

Η κανονική έκφραση δέχεται ψηφία ASCII και ο έλεγχος matched(0).length εξασφαλίζει ότι καταναλώθηκε ολόκληρη η είσοδος: σε ορισμένες μηχανές regex το $ μπορεί να ταιριάξει πριν από τελική αλλαγή γραμμής. Το όριο πέντε χαρακτήρων περιορίζει και τη μετατροπή· αρχικά μηδενικά επιτρέπονται μόνο μέσα σε αυτό το όριο. Απορρίπτονται κενά, πρόσημα και μεικτό κείμενο. Ο δεύτερος έλεγχος απορρίπτει το μηδέν και αριθμούς πάνω από 65535. Η κενή είσοδος επίσης απορρίπτεται. Με Null<Int> ο καλών οφείλει να αντιμετωπίσει την απόρριψη, αντί να τη συγχέει με έγκυρη θύρα.

Είσοδοι πάνω από πέντε χαρακτήρες απορρίπτονται πριν από τη μετατροπή. Η πολιτική απορρίπτει επίσης έξι ψηφία με αρχικά μηδενικά, ακόμη κι αν η αριθμητική τους τιμή θα ήταν εντός ορίων· τεκμηρίωσε αυτή την επιλογή.

Αρνητικές δοκιμές και εξέλιξη

Για ολοκλήρωση παράδωσε έκδοση εργαλείου, εντολές, εισόδους πριν/μετά, προβλέψεις, πραγματικές εξόδους, μία ελεγχόμενη αστοχία και σημείωση φορητότητας. Οι αναμενόμενες τιμές δεν παρουσιάζονται ως αποτέλεσμα τοπικής εκτέλεσης Haxe.

Haxe — Διαδρομή ουσιαστικής εξάσκησης

Στόχος και περιβάλλον

Η Haxe ελέγχει τους τύπους του πηγαίου κώδικα και παράγει κώδικα για διαφορετικούς στόχους. Αυτό δεν εγγυάται ότι οι βιβλιοθήκες ή οι αριθμητικοί τύποι συμπεριφέρονται παντού με τον ίδιο τρόπο. Εργάσου σε προσωρινό φάκελο με εγκατεστημένο μεταγλωττιστή Haxe. Για τη σύγκριση με JavaScript χρειάζεται επιπλέον Node.js. Κατάγραψε τις εκδόσεις με haxe --version και node --version.

Αποθήκευσε το ακόλουθο ως Main.hx (το κεφαλαίο M έχει σημασία σε συστήματα με διάκριση πεζών/κεφαλαίων):

class Main {
  static function average(values:Array<Int>):Null<Float> {
    if (values.length == 0) return null;
    var total = 0;
    for (value in values) total += value;
    return total / values.length;
  }

  static function main() {
    trace(average([2, 4, 6]));
    trace(average([]));
    trace(average([-2, 2]));
    trace(average([1, 2]));
  }
}

Εκτέλεσε haxe --main Main --interp. Για δεύτερο στόχο, χρησιμοποίησε haxe --main Main --js main.js και στη συνέχεια node main.js. Η trace συνήθως εμφανίζει μαζί με την τιμή και όνομα αρχείου/γραμμή· σύγκρινε τις τιμές, όχι την ακριβή μορφή του μηνύματος.

Ανάλυση και αναμενόμενες τιμές

Οι τέσσερις τιμές πρέπει να είναι 4, null, 0 και 1.5. Ο αριθμητικός μέσος κενής λίστας δεν ορίζεται, επομένως το Null<Float> δηλώνει απουσία αποτελέσματος αντί να επιστρέφει παραπλανητικό μηδέν. Η επανάληψη διατρέχει n στοιχεία: χρόνος O(n) και επιπλέον χώρος O(1). Σε πολύ μεγάλους αριθμούς το άθροισμα Int ενδέχεται να υπερχειλίσει πριν από τη διαίρεση.

Ο τύπος του value προκύπτει ως Int από το Array<Int>. Αν αντικαταστήσεις το [1, 2] με ["1", "2"], αναμένεται σφάλμα ελέγχου τύπων. Αυτό είναι διαφορετικό από το έγκυρο κενό Array<Int>, για το οποίο επιστρέφεται null.

Διάγνωση και οριακές δοκιμές

Κριτήρια ολοκλήρωσης

Πρώτα εξήγησε γιατί η κενή λίστα δεν δίνει μηδέν. Έπειτα άλλαξε την επιστρεφόμενη τιμή σε ρητό enum, π.χ. NoData | Mean(value:Float), και χειρίσου και τις δύο περιπτώσεις χωρίς μη ασφαλείς μετατροπές τύπων. Τέλος σύγκρινε διερμηνευτή και JavaScript, κρατώντας πηγαίο κώδικα, εντολές, εκδόσεις, προβλέψεις, παρατηρήσεις και ένα πραγματικό διαγνωστικό μεταγλωττιστή. Οι τιμές εδώ είναι αναμενόμενες βάσει ανάλυσης, όχι ισχυρισμός πραγματικής εκτέλεσης Haxe κατά τη συγγραφή.