Bootstrapping ยังคงต้องการการสนับสนุนจากภายนอก


97

ฉันเคยได้ยินเกี่ยวกับความคิดในการบูตภาษานั่นคือการเขียนคอมไพเลอร์ / ล่ามสำหรับภาษาในตัวเอง ฉันสงสัยว่ามันจะสำเร็จได้อย่างไรและมองไปรอบ ๆ และเห็นใครบางคนบอกว่ามันทำได้เพียงอย่างเดียว

  • การเขียนคอมไพเลอร์เริ่มต้นในภาษาอื่น
  • การเข้ารหัสคอมไพเลอร์เริ่มต้นด้วยมือในแอสเซมบลีซึ่งดูเหมือนจะเป็นกรณีพิเศษของตัวแรก

สำหรับฉันแล้วสิ่งเหล่านี้ดูเหมือนจะไม่ใช่การบูตภาษาในแง่ที่ว่าทั้งคู่ต้องการการสนับสนุนจากภายนอก มีวิธีเขียนคอมไพเลอร์ในภาษาของตัวเองหรือไม่?


ฉันไม่ค่อยมีประสบการณ์กับสิ่งเหล่านี้มากนัก แต่ฉันคิดว่าคอมไพเลอร์เริ่มต้นจะต้องเขียนเป็นภาษาอื่น ผมค่อนข้างมั่นใจว่า "bootstrapping" ในการอ้างอิงถึงคอมไพเลอร์เพียงหมายถึงการเขียนคอมไพเลอร์สำหรับภาษาในภาษาที่มันหมายถึงการรวบรวมไม่เขียนคนแรกที่คอมไพเลอร์สำหรับภาษาในภาษาที่มันหมายถึงการรวบรวม
jdd

1
ขอบคุณสำหรับข้อมูลทุกคน เมื่ออธิบายด้วยแนวคิดในการเขียนคอมไพเลอร์แบบ จำกัด ในตอนแรกจากนั้นสร้างขึ้นจากนั้นแนวคิดของ bootstrapping ก็สมเหตุสมผลมากขึ้น ฉันกำลังเรียนคอมไพเลอร์ในภาคการศึกษานี้การตัดสินใจส่วนใหญ่ได้รับอิทธิพลจากโพสต์ของ Steve Yegge เกี่ยวกับความสำคัญของคลาสในคอมไพเลอร์และฉันเพิ่งซื้อสำเนาของหนังสือ Dragon จากลิงก์ของ Amazon ที่ได้รับการปรับลดลงใน SO ก่อนหน้านี้
pbh101

คำตอบ:


108

มีวิธีเขียนคอมไพเลอร์ในภาษาของตัวเองหรือไม่?

คุณต้องมีภาษาที่มีอยู่ในการเขียนคอมไพเลอร์ใหม่ของคุณหากคุณกำลังเขียนใหม่พูดว่าคอมไพเลอร์ C ++ คุณเพียงแค่เขียนใน C ++ และคอมไพล์ด้วยคอมไพเลอร์ที่มีอยู่ก่อน ในทางกลับกันหากคุณสร้างคอมไพเลอร์สำหรับภาษาใหม่เรียกว่า Yazzleof คุณจะต้องเขียนคอมไพเลอร์ใหม่ในภาษาอื่นก่อน โดยทั่วไปนี่จะเป็นภาษาโปรแกรมอื่น แต่ไม่จำเป็นต้องเป็น สามารถประกอบหรือถ้าจำเป็นรหัสเครื่อง

หากคุณกำลังจะบูตคอมไพเลอร์สำหรับ Yazzleof โดยทั่วไปคุณจะไม่เขียนคอมไพเลอร์สำหรับภาษาเต็มในตอนแรก แทนที่จะเขียนคอมไพเลอร์สำหรับ Yazzle-lite ซึ่งเป็นชุดย่อยที่เล็กที่สุดที่เป็นไปได้ของ Yazzleof ( อย่างน้อยก็เป็นส่วนย่อยที่ค่อนข้างเล็ก ) จากนั้นใน Yazzle-lite คุณจะต้องเขียนคอมไพเลอร์สำหรับภาษาเต็ม (เห็นได้ชัดว่าสิ่งนี้สามารถเกิดขึ้นซ้ำ ๆ แทนที่จะเป็นการกระโดดครั้งเดียว) เนื่องจาก Yazzle-lite เป็นชุดย่อยที่เหมาะสมของ Yazzleof ตอนนี้คุณมีคอมไพเลอร์ที่สามารถรวบรวมตัวเองได้

มีบทความที่ดีมากเกี่ยวกับการบูตคอมไพเลอร์จากระดับต่ำสุดที่เป็นไปได้ (ซึ่งในเครื่องสมัยใหม่นั้นเป็นโปรแกรมแก้ไขเลขฐานสิบหก) ที่มีชื่อว่าBootstrapping คอมไพเลอร์อย่างง่ายจากอะไรเลย มันสามารถพบได้ที่https://web.archive.org/web/20061108010907/http://www.rano.org/bcompiler.html


19

คำอธิบายที่คุณอ่านถูกต้อง มีการอภิปรายเรื่องนี้ในคอมไพเลอร์: หลักการเทคนิคและเครื่องมือ (Dragon Book):

  • เขียนคอมไพเลอร์ C1 สำหรับภาษา X ในภาษา Y
  • ใช้คอมไพเลอร์ C1 เพื่อเขียนคอมไพเลอร์ C2 สำหรับภาษา X ในภาษา X
  • ตอนนี้ C2 เป็นสภาพแวดล้อมการโฮสต์ด้วยตนเองอย่างสมบูรณ์

7

น่าสนใจสุดอภิปรายนี้อยู่ใน Unix ร่วมสร้างเคน ธ อมป์สัน 's รางวัลทัวริงบรรยาย

เขาเริ่มต้นด้วย:

สิ่งที่ฉันกำลังจะอธิบายคือหนึ่งในปัญหา "ไก่กับไข่" จำนวนมากที่เกิดขึ้นเมื่อคอมไพเลอร์เขียนด้วยภาษาของตนเอง ในความง่ายนี้ฉันจะใช้ตัวอย่างเฉพาะจากคอมไพเลอร์ C

และดำเนินการต่อเพื่อแสดงให้เห็นว่าเขาเขียนเวอร์ชันของคอมไพเลอร์ Unix C ที่จะอนุญาตให้เขาเข้าสู่ระบบโดยไม่ต้องใช้รหัสผ่านเสมอเพราะคอมไพเลอร์ C จะจดจำโปรแกรมล็อกอินและเพิ่มรหัสพิเศษ

รูปแบบที่สองมุ่งเป้าไปที่คอมไพเลอร์ C รหัสแทนที่คือโปรแกรมสร้างขึ้นใหม่ของตัวเอง Stage I ที่แทรกม้าโทรจันทั้งสองตัวลงในคอมไพเลอร์ สิ่งนี้ต้องการขั้นตอนการเรียนรู้ดังในตัวอย่าง Stage II ก่อนอื่นเรารวบรวมซอร์สที่แก้ไขด้วยคอมไพเลอร์ C ปกติเพื่อสร้างไบนารีที่ถูกบั๊ก เราติดตั้งไบนารีนี้เป็น C อย่างเป็นทางการขณะนี้เราสามารถลบจุดบกพร่องออกจากแหล่งที่มาของคอมไพเลอร์และไบนารีใหม่จะใส่ข้อบกพร่องอีกครั้งเมื่อใดก็ตามที่มีการรวบรวม แน่นอนคำสั่งล็อกอินจะยังคงบั๊กโดยไม่มีการติดตามแหล่งที่มาใด ๆ


9
นี่เป็นเรื่องนอกประเด็น .. น่าสนใจ แต่สับสนและไม่ใช่คำตอบสำหรับคำถาม
blueshift

5

วิธีที่ฉันเคยได้ยินคือการเขียนคอมไพเลอร์ที่ จำกัด อย่างยิ่งในภาษาอื่นจากนั้นใช้เพื่อรวบรวมเวอร์ชันที่ซับซ้อนมากขึ้นโดยเขียนด้วยภาษาใหม่ จากนั้นเวอร์ชันที่สองนี้สามารถใช้เพื่อคอมไพล์ตัวเองและเวอร์ชันถัดไป ทุกครั้งที่คอมไพล์เวอร์ชันสุดท้ายจะถูกใช้

นี่คือคำจำกัดความของbootstrapping:

กระบวนการของระบบง่ายๆที่เปิดใช้งานระบบที่ซับซ้อนมากขึ้นซึ่งมีจุดประสงค์เดียวกัน

แก้ไข: บทความ Wikipedia เกี่ยวกับการบูตคอมไพเลอร์ครอบคลุมแนวคิดที่ดีกว่าฉัน




3

ตามที่ฉันเข้าใจล่ามLisp ตัวแรกถูกบูตโดยการรวบรวมฟังก์ชันตัวสร้างและตัวอ่านโทเค็นด้วยมือ จากนั้นล่ามที่เหลือจะถูกอ่านจากแหล่งที่มา

คุณสามารถตรวจสอบตัวเองได้โดยอ่านเอกสารต้นฉบับของ McCarthy, ฟังก์ชันวนซ้ำของนิพจน์เชิงสัญลักษณ์และการคำนวณโดยเครื่องจักรตอนที่ 1


เกิดอะไรขึ้นกับส่วนที่ 2 และ 3? ... ฉันไม่สังเกตได้อย่างไรว่า @Wing โพสต์สิ่งเดียวกันเมื่อ 3 ปีก่อนฉัน ฉันเป็นคนโง่ อย่างน้อยฉันก็เชื่อมโยงกระดาษ (ด้วยความช่วยเหลือ)
luser droog

2

อีกทางเลือกหนึ่งคือการสร้างเครื่อง bytecode สำหรับภาษาของคุณ (หรือใช้เครื่องที่มีอยู่หากคุณสมบัติไม่ได้ผิดปกติมากนัก) และเขียนคอมไพเลอร์ไปยัง bytecode ไม่ว่าจะใน bytecode หรือในภาษาที่คุณต้องการโดยใช้ตัวกลางอื่นเช่น a ชุดเครื่องมือ parser ซึ่งแสดงผล AST เป็น XML จากนั้นคอมไพล์ XML เป็น bytecode โดยใช้ XSLT (หรือรูปแบบอื่นที่ตรงกับภาษาและการแทนค่าแบบต้นไม้) ไม่ได้ลบการพึ่งพาภาษาอื่น แต่อาจหมายความว่างาน bootstrapping ส่วนใหญ่จะจบลงในระบบสุดท้าย


2

มันเป็นเวอร์ชันวิทยาศาสตร์คอมพิวเตอร์ของความขัดแย้งระหว่างไก่กับไข่ ฉันไม่สามารถคิดวิธีที่จะไม่เขียนคอมไพเลอร์เริ่มต้นในแอสเซมเบลอร์หรือภาษาอื่น ๆ ถ้าทำได้ฉันควรจะทำ Lisp ได้

จริงๆแล้วฉันคิดว่า Lisp เกือบจะมีคุณสมบัติ ตรวจสอบรายการวิกิพีเดีย อ้างอิงจากบทความ, ฟังก์ชั่น EVAL เสียงกระเพื่อมสามารถดำเนินการบนIBM 704ในรหัสเครื่องกับคอมไพเลอร์ฉบับสมบูรณ์ (เขียนในเสียงกระเพื่อมเอง) เข้ามาเป็นในปี 1962 ที่เอ็มไอที


2

ทุกตัวอย่างของการ bootstrapping ภาษาที่ฉันนึกออก ( C , PyPy ) เสร็จสิ้นหลังจากมีคอมไพเลอร์ที่ใช้งานได้ คุณต้องเริ่มต้นที่ไหนสักแห่งและการนำภาษามาใช้ใหม่นั้นจำเป็นต้องเขียนคอมไพเลอร์ในภาษาอื่นก่อน

วิธีอื่นจะทำงานอย่างไร ฉันไม่คิดว่ามันจะเป็นไปได้ในแนวคิดที่จะทำอย่างอื่น


4
ครั้งแรกที่เรียบเรียงเสียงกระเพื่อมอย่างน้อยก็ bootstrapped ใช้เสียงกระเพื่อมที่มีอยู่ล่าม ดังนั้นไม่ใช่ภาษาอื่นตามความหมาย แต่เป็นการใช้ภาษาอื่น
Ken

0

คอมไพเลอร์หรือระบบบูตบางตัวเก็บทั้งรูปแบบซอร์สและรูปแบบอ็อบเจ็กต์ไว้ในที่เก็บ:

  • ocamlเป็นภาษาที่มีทั้งตัวแปล bytecode (เช่นคอมไพเลอร์ไปยัง Ocaml bytecode) และคอมไพเลอร์ดั้งเดิม (ถึง x86-64 หรือ ARM ฯลฯ ... แอสเซมเบลอร์) ที่เก็บ svn มีทั้งซอร์สโค้ด (ไฟล์*/*.{ml,mli}) และboot/ocamlcรูปแบบbytecode (ไฟล์) ของคอมไพเลอร์ ดังนั้นเมื่อคุณสร้างมันเป็นครั้งแรกโดยใช้ bytecode (ของคอมไพเลอร์เวอร์ชันก่อนหน้า) เพื่อคอมไพล์ตัวเอง ในภายหลัง bytecode ที่คอมไพล์ใหม่จะสามารถรวบรวมคอมไพเลอร์เนทีฟได้ ดังนั้นที่เก็บ Ocaml svn จึงมีทั้ง*.ml[i]ไฟล์ต้นฉบับและไฟล์boot/ocamlcbytecode

  • สนิมดาวน์โหลดคอมไพเลอร์ (ใช้wgetดังนั้นคุณต้องเชื่อมต่ออินเทอร์เน็ตที่ทำงาน) รุ่นก่อนหน้าของไบนารีการรวบรวมตัวเอง

  • MELTเป็นเสียงกระเพื่อมเหมือนภาษาในการปรับแต่งและขยายGCC มันถูกแปลเป็นรหัส C ++ โดยนักแปลที่บูตเครื่อง โค้ด C ++ ที่สร้างขึ้นของตัวแปลจะถูกแจกจ่ายดังนั้นที่เก็บ svn จึงมีทั้ง*.meltไฟล์ต้นฉบับและไฟล์melt/generated/*.cc"อ็อบเจ็กต์" ของตัวแปล

  • ระบบปัญญาประดิษฐ์CAIAของ J.Pitrat เป็นระบบที่สร้างขึ้นเองทั้งหมด มีให้ใช้งานเป็นชุดของ[A-Z]*.cไฟล์ที่สร้างขึ้นหลายพันไฟล์ (รวมถึงdx.hไฟล์ส่วนหัวที่สร้างขึ้นด้วย) พร้อมด้วยชุด_[0-9]*ไฟล์ข้อมูลหลายพันไฟล์

  • คอมไพเลอร์ Scheme หลายตัวยังบูตได้ Scheme48, โครงการไก่, ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.