สร้างภาษาโปรแกรมของคุณเอง — interpreter ด้วย Rust std ล้วน
ก่อนเริ่ม — สิ่งที่ควรมีมาก่อน
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม — สิ่งที่ควรมีมาก่อน”ต้องมี Rust ระดับอ่านออกและคอมไพล์เองได้ ส่วนทฤษฎีคอมไพเลอร์ไม่ต้องมีมาก่อนเลย
- Rust ระดับที่ผ่าน ownership กับ borrow มาแล้ว ไม่ต้องเชี่ยวชาญ แต่ต้องเคยโดน borrow checker ปฏิเสธและเข้าใจว่าทำไม คอร์สนี้จะพาไปเจอจุดที่มันปฏิเสธด้วยเหตุผลที่ดี
- ไม่ต้องรู้ทฤษฎีคอมไพเลอร์มาก่อน ไม่มีบทไหนขอให้รู้จัก LL, LR หรือ context-free grammar มาก่อน ทุกคำที่ใช้ถูกอธิบายตอนที่มันโผล่มาครั้งแรก
- ไม่ต้องติดตั้งอะไรเพิ่มเลย นอกจาก Rust toolchain ที่มีอยู่แล้ว เพราะทั้งคอร์สใช้ standard library ล้วน
- ถ้าเพิ่งจบคอร์สอื่นในเส้นทาง Rust คอร์สนี้เป็นบทปิดของซีรีส์ แต่ไม่ได้ต่อยอด code จากคอร์สไหน เริ่มจาก file เปล่าได้เลย
เส้นขอบเขต — คอร์สนี้สร้างอะไร และไม่สร้างอะไร
หัวข้อที่มีชื่อว่า “เส้นขอบเขต — คอร์สนี้สร้างอะไร และไม่สร้างอะไร”หัวข้อนี้ประกาศขอบเขตล่วงหน้า เพื่อไม่ให้ใครอ่านจบแล้วรู้สึกว่าถูกสัญญาเกินจริง
สิ่งที่ได้เมื่อจบคือ interpreter ที่รันภาษาซึ่งมีตัวแปร เงื่อนไข ลูป ฟังก์ชัน closure class และ method ได้จริง พร้อม REPL และตัวรัน script
สิ่งที่คอร์สนี้ ไม่ ทำ
หัวข้อที่มีชื่อว่า “สิ่งที่คอร์สนี้ ไม่ ทำ”รายการนี้เป็นเส้นขอบเขต ไม่ใช่ข้อแก้ตัว — ทุกข้อจงใจตัดออกเพื่อให้ส่วนที่เหลือรันได้จริงใน 8 บท
- ไม่มี inheritance class ในคอร์สนี้มี property กับ method แต่สืบทอดกันไม่ได้ นี่คือของที่ ถูกตัดออกอย่างตั้งใจ และบทที่ 8 จะบอกว่าถ้าอยากทำต่อต้องเติมอะไร
- ไม่ใช่ bytecode VM คอร์สนี้เดินบนต้นไม้โดยตรง ซึ่งเข้าใจง่ายกว่าและช้ากว่าโดยธรรมชาติ การคอมไพล์ลง bytecode เป็นคนละคอร์ส ไม่ใช่บทที่ 9
- ไม่มี garbage collector เรายืมระบบ ownership กับ
Rcของ Rust มาใช้แทน ซึ่งแลกมาด้วย ข้อจำกัดจริงที่บทที่ 7 จะพูดถึงตรงๆ - ไม่อ้างเรื่องความเร็วเลยสักจุด ไม่มีตัวเลข benchmark ไม่มีการเทียบกับภาษาอื่น เพราะคอร์สนี้ไม่ได้วัดเรื่องนั้น
ทำไมไม่ใช่การแปลตำราที่ทุกคนอ่าน
หัวข้อที่มีชื่อว่า “ทำไมไม่ใช่การแปลตำราที่ทุกคนอ่าน”หัวข้อนี้บอกว่าคอร์สนี้ต่างจากต้นทางตรงไหน และทำไมความต่างนั้นถึงเป็นสาระ
ตำราต้นทางเขียนด้วย Java ซึ่งไม่มี sum type จึงต้องใช้ Visitor pattern เพื่อให้เพิ่ม การทำงานใหม่บนโครงสร้างเดิมได้โดยไม่แก้ทุกคลาส
Rust ไม่มีปัญหานั้น enum เก็บทุกกรณีไว้ในที่เดียว และ match บังคับให้เขียนครบทุกกรณี
ตั้งแต่ตอนคอมไพล์ สิ่งที่ Java ต้องใช้แปดคลาสกับ interface หนึ่งตัว Rust เขียนเป็น
enum เดียวกับ match เดียว
ความต่างนี้ไม่ได้อยู่แค่ผิว มันเปลี่ยนลำดับการสอนทั้งคอร์ส และเปลี่ยนว่าอะไรคือ ส่วนที่ยาก จุดที่ยากที่สุดของคอร์สนี้ไม่ใช่ parser แต่คือตอนที่ ownership บอกว่า environment แบบที่ตำราวาดไว้ เขียนใน Rust ตรงๆ ไม่ได้
code ทุกบรรทัดมาจาก crate ที่คุณคอมไพล์เองได้
หัวข้อที่มีชื่อว่า “code ทุกบรรทัดมาจาก crate ที่คุณคอมไพล์เองได้”หัวข้อนี้อธิบายว่าทำไมผู้อ่านตรวจสอบ code ในคอร์สนี้เองได้ทั้งหมด
code ทุกบล็อกในบทเรียนไม่ได้ถูกพิมพ์ขึ้นมาใหม่ มันถูกคัดมาจาก file จริงใน
scripts/rust-interpreter/ ที่ commit ไว้ในรีโปนี้ และมีเทสต์เทียบทีละ byte
ผลรันทุกอันที่บทเรียนแสดง ก็ถูกคัดมาจาก stdout ที่รันจริงเช่นกัน พร้อมป้ายกำกับว่า
รันด้วย rustc รุ่นไหนและ edition อะไร ถ้าคุณรันแล้วได้ไม่เท่ากัน แปลว่ามีอะไรผิด
ไม่ใช่ “แล้วแต่เครื่อง”
เส้นทางการเรียน
หัวข้อที่มีชื่อว่า “เส้นทางการเรียน”แผนผังนี้จะเติมขึ้นเองเมื่อบทเรียนถูกเพิ่มเข้ามา