นักพัฒนาสร้าง C Compiler ด้วย Python เพียง 500 บรรทัด จุดประกายการถอดถอนเรื่องแนวทางการออกแบบ Compiler

ทีมชุมชน BigGo
นักพัฒนาสร้าง C Compiler ด้วย Python เพียง 500 บรรทัด จุดประกายการถอดถอนเรื่องแนวทางการออกแบบ Compiler

นักพัฒนาคนหนึ่งสามารถสร้าง C compiler ที่ใช้งานได้จริงด้วยโค้ด Python เพียง 500 บรรทัดเท่านั้น โดยมี WebAssembly เป็นรูปแบบเอาต์พุต ความสำเร็จที่น่าประทับใจนี้ได้จุดประกายการอภิปรายในชุมชนโปรแกรมเมอร์เกี่ยวกับปรัชญาการออกแบบ compiler และการแลกเปลี่ยนระหว่างความเรียบง่ายของโค้ดกับฟังก์ชันการทำงาน

โปรเจกต์นี้แสดงถึงแนวทางมินิมัลลิสต์ในการสร้าง compiler โดยตัดฟีเจอร์ดั้งเดิมของ C หลายอย่างออกไปเพื่อมุ่งเน้นไปที่ฟังก์ชันหลัก compiler นี้รองรับเฉพาะชนิดข้อมูลจำนวนเต็มและการดำเนินการพื้นฐาน โดยจงใจตัดฟีเจอร์ที่ซับซ้อนออกไป เช่น pointers, structs, ขนาดข้อมูลแบบต่างๆ และการจัดการข้อผิดพลาดที่เหมาะสม เพื่อให้อยู่ในขีดจำกัดของจำนวนบรรทัดที่เข้มงวด

คุณสมบัติที่รองรับ

  • รองรับเฉพาะประเภทข้อมูลจำนวนเต็ม
  • การดำเนินการทางคณิตศาสตร์พื้นฐาน
  • การเรียกใช้ฟังก์ชันและ stack frames
  • ค่าคงที่สตริงผ่าน StringPool
  • ตัวแปรท้องถิ่นและการควบคุมการทำงานพื้นฐาน

Single-Pass เทียบกับการออกแบบแบบหลายขั้นตอนแบบดั้งเดิม

การถกเถียงในชุมชนมุ่งเน้นไปที่การเลือกใช้แนวทาง single-pass compilation แทนที่จะเป็น pipeline แบบ lexer-parser-AST-emitter ที่เป็นแบบดั้งเดิม นักพัฒนาบางคนตั้งคำถามว่าแนวทางนี้เรียบง่ายกว่าจริงหรือไม่ โดยโต้แย้งว่าการสร้าง Abstract Syntax Tree (AST) อาจจะง่ายกว่าในการใช้งานจริงและจะช่วยให้สามารถทำการปรับปรุงประสิทธิภาพพื้นฐานผ่าน pattern matching ได้ อย่างไรก็ตาม คนอื่นๆ ชี้ให้เห็นว่าโค้ดที่มีบรรทัดน้อยกว่าไม่ได้หมายความว่าจะง่ายกว่าในการใช้งาน และแนวทาง single-pass ก็ช่วยลดความซับซ้อนในการจัดการ intermediate representations

การตัดสินใจทางเทคนิคที่สำคัญ

  • สถาปัตยกรรมคอมพิวเตอร์แบบ stack-based (หลีกเลี่ยงความซับซ้อนของการจัดสรร register)
  • รูปแบบเอาต์พุตเป้าหมายเป็น WebAssembly
  • แนวทางการคอมไพล์แบบ single-pass
  • การใช้งาน Python เพื่อลดโค้ดส่วนเสริมที่ซ้ำซาก

WebAssembly เป็นเป้าหมายที่ไม่ธรรมดา

การตัดสินใจเลือก WebAssembly แทนที่จะเป็น native machine code หรือ custom runtime ได้ดึงดูดความสนใจ ผู้เขียนยอมรับว่าการเลือกนี้เป็นเพื่อความสนุกสนานส่วนหนึ่ง แม้ว่าจะสร้างความท้าทายที่น่าสนใจก็ตาม instruction set แบบ stack-based ของ WebAssembly เข้ากันได้ดีกับการออกแบบแบบ stack-based ของ compiler แต่การขาด registers แบบดั้งเดิมและความซับซ้อนในการแบ่ง control flow ก็สร้างอุปสรรคในการใช้งานที่เป็นเอกลักษณ์

เทคนิคทางวิศวกรรมที่ชาญฉลาดและการแลกเปลี่ยน

compiler นี้ใช้เทคนิคประหยัดพื้นที่หลายอย่างที่เสียสละแนวปฏิบัติที่ดีแบบดั้งเดิมเพื่อความกระชับ ระบบ StringPool จัดการค่าคงที่แบบสตริงอย่างมีประสิทธิภาพ ในขณะที่การใช้ dataclasses ของ Python ช่วยลดโค้ดที่ซ้ำซากได้อย่างมาก ผู้เขียนจงใจเลือกที่จะคัดลอก intermediate representations แทนที่จะแก้ไข structures โดยแลกเปลี่ยนประสิทธิภาพหน่วยความจำกับความเรียบง่ายของโค้ด

dictionaries ของผมจะเป็น linked-list การค้นหา key จะกลายเป็น linear search... 500 บรรทัดถือว่าเข้มงวดมาก แต่ IOCCC ให้เทคนิคมากมายที่จะช่วยลดจำนวนบรรทัดลงได้

โครงสร้างข้อมูลหลัก

  • ValueRef: ตำแหน่งสำหรับจัดเก็บ/เรียกใช้ค่าต่างๆ
  • Const: ค่าคงที่เป็นตัวเลขจำนวนเต็ม
  • GlobalRef: ตำแหน่งส่วนกลางสำหรับค่าคงที่แบบสตริง
  • NameRef: ชื่อที่มีค่า offset (สามารถซ้อนกันได้อย่างไม่จำกัด)
  • TypeRef: ข้อมูลประเภทสำหรับค่าต่างๆ
  • Alloc/Free: การจัดการพื้นที่ stack

คุณค่าทางการศึกษาและความเชื่อมโยงทางภาษาศาสตร์

โปรเจกต์นี้ได้จุดประกายความสนใจในหมู่นักพัฒนาที่เพิ่งเริ่มต้นศึกษาการสร้าง compiler โดยบางคนสังเกตเห็นความเชื่อมโยงที่น่าประหลาดใจระหว่างการออกแบบ compiler และภาษาศาสตร์ ความสัมพันธ์นี้มาจากงานของ Noam Chomsky เกี่ยวกับ formal grammars สำหรับภาษาธรรมชาติ ซึ่งนักวิทยาศาสตร์คอมพิวเตอร์ได้นำมาปรับใช้สำหรับการออกแบบภาษาโปรแกรมในภายหลัง ทฤษฎี formal grammar ที่อธิบายโครงสร้างของภาษามนุษย์ให้รากฐานทางคณิตศาสตร์สำหรับการแยกวิเคราะห์ภาษาโปรแกรม

ความท้าทายและการตอบสนองของชุมชน

โปรเจกต์นี้ได้สร้างแรงบันดาลใจให้เกิดความท้าทายที่สนุกสนานในชุมชน รวมถึงข้อเสนอในการเขียน Python compiler ด้วย C เพียง 500 บรรทัด แม้ว่าจะเป็นไปได้ในทางเทคนิค แต่การใช้งานดังกล่าวจะต้องมีการประนีประนอมอย่างมาก รวมถึงการใช้ linear search algorithms แทน hash tables ที่มีประสิทธิภาพ และการจัดการข้อผิดพลาดที่น้อยที่สุด ความเห็นพ้องต้องกันคือแม้ว่าจะทำได้ แต่ compiler ที่ได้จะไม่สามารถใช้งานได้จริงสำหรับแอปพลิเคชันในโลกจริง

C compiler 500 บรรทัดนี้แสดงให้เห็นว่าผลลัพธ์ที่น่าประทับใจสามารถทำได้ด้วยข้อจำกัดที่เข้มงวด แม้ว่าผลิตภัณฑ์สุดท้ายจะเสียสละฟีเจอร์หลายอย่างที่ production compilers ต้องการก็ตาม มันทำหน้าที่เป็นแบบฝึกหัดทางการศึกษาที่ยอดเยี่ยมและเป็นการพิสูจน์แนวคิด แสดงให้เห็นว่าหลักการพื้นฐานของ compiler สามารถกลั่นให้เป็นโค้ดที่กะทัดรัดได้อย่างน่าประหลาดใจ

อ้างอิง: Writing a C compiler in 500 lines of Python