เป็นไปได้ไหมที่จะสร้างล่ามแบบ "bootstrapped" โดยไม่ขึ้นอยู่กับล่ามดั้งเดิม?


21

ตามที่Wikipedia คำว่า "bootstrapping" ในบริบทของการเขียนคอมไพเลอร์หมายถึงสิ่งนี้ :

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

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

คุณเขียนรุ่นล่ามครั้งแรกของคุณในภาษาของXและล่ามเป็นภาษาใหม่ที่คุณกำลังสร้างที่เรียกว่าY คุณใช้คอมไพเลอร์ภาษาXเพื่อสร้างไฟล์ปฏิบัติการ ขณะนี้คุณสามารถตีความไฟล์ที่เขียนในภาษาของคุณใหม่Yใช้ล่ามที่เขียนในภาษาX

ทีนี้เท่าที่ฉันเข้าใจเพื่อที่จะสามารถ "บู๊ตสแตรป" ล่ามที่คุณเขียนเป็นภาษาXคุณต้องเขียนล่ามเป็นภาษาYอีกครั้ง แต่นี่คือการจับ: แม้ว่าคุณจะเขียนล่ามทั้งในภาษาYคุณยังจะต้องเดิมล่ามที่คุณเขียนในภาษาX เนื่องจากการเรียกใช้ล่ามในภาษาYคุณจะต้องตีความไฟล์ต้นฉบับ แต่สิ่งที่จะแปลความหมายไฟล์ต้นฉบับ? แน่นอนมันไม่มีอะไรเลยดังนั้นคุณถูกบังคับให้ต้องใช้ล่ามคนแรก

ไม่ว่าคุณจะมีล่ามใหม่กี่คนในภาษาYคุณจะต้องใช้ล่ามตัวแรกที่เขียนด้วยXเพื่อตีความล่ามต่อไป สิ่งนี้ดูเหมือนจะเป็นปัญหาเพียงเพราะธรรมชาติของล่าม

อย่างไรก็ตามในด้านพลิกนี้บทความวิกิพีเดียล่ามจริงพูดเกี่ยวกับล่ามตัวเองโฮสติ้ง นี่เป็นข้อความที่ตัดตอนมาเล็กน้อยซึ่งมีความเกี่ยวข้อง:

Self-interpreter เป็นล่ามภาษาโปรแกรมที่เขียนในภาษาโปรแกรมซึ่งสามารถตีความได้เอง ตัวอย่างคือล่ามพื้นฐานที่เขียนในภาษาเบสิก ตัวแปลภาษาเองเกี่ยวข้องกับคอมไพเลอร์ที่โฮสต์ด้วยตนเอง

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

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

ตอนนี้บทความดังกล่าวข้างต้นเชื่อมโยงไปยังบทความอื่นในวิกิพีเดียซึ่งให้ตัวอย่างบางส่วนของควรล่ามตัวเองโฮสติ้ง เมื่อตรวจสอบอย่างใกล้ชิด แต่ดูเหมือนว่า "ล่าม" เป็นส่วนสำคัญของล่ามที่จัดการโฮสต์ด้วยตนเอง (โดยเฉพาะอย่างยิ่งที่พบบ่อยเช่น PyPy หรือ Rubinius) ถูกเขียนในภาษาอื่นเช่น C ++ หรือ C

ดังนั้นสิ่งที่ฉันอธิบายข้างต้นเป็นไปได้? ล่ามที่โฮสต์โดยตนเองสามารถเป็นอิสระจากโฮสต์เดิมได้หรือไม่ ถ้าเป็นเช่นนั้นจะทำเช่นนี้ได้อย่างไร?

คำตอบ:


24

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

ไม่ว่าคุณจะมีล่ามใหม่กี่คนในภาษาYคุณจะต้องใช้ล่ามตัวแรกที่เขียนด้วยXเพื่อตีความล่ามต่อไป สิ่งนี้ดูเหมือนจะเป็นปัญหาเพียงเพราะธรรมชาติของล่าม

แก้ไข. สิ่งที่คุณสามารถทำคือการเขียนเรียบเรียงจากYไปX (หรือภาษาอื่นที่คุณมีล่าม) และคุณยังสามารถทำในY จากนั้นคุณสามารถเรียกใช้คอมไพเลอร์Yของคุณที่เขียนด้วยYในล่ามY ที่เขียนในX (หรือล่ามY ที่เขียนในY ที่ทำงานบนล่ามY ที่เขียนในXหรือในล่ามY ที่เขียนในY ที่ทำงานบนล่ามY Yกำลังวิ่งอยู่บนYล่ามที่เขียนด้วยXหรือ ... ad infinitum) เพื่อรวบรวมล่ามYของคุณที่เขียนในYเป็นXเพื่อให้คุณสามารถดำเนินการกับล่ามXได้ ด้วยวิธีนี้คุณได้กำจัดล่ามYของคุณที่เขียนด้วยXแต่ตอนนี้คุณต้องการล่ามX (เรารู้ว่าเรามีล่ามอยู่แล้ว แต่เนื่องจากมิเช่นนั้นเราไม่สามารถวิ่งล่ามX ที่เขียนเป็นY ) และคุณ ต้องเขียนY -to- X - compiler ก่อน

อย่างไรก็ตามในทางกลับกันบทความวิกิพีเดียเกี่ยวกับล่ามจริง ๆ แล้วพูดถึงล่ามด้วยตนเอง นี่เป็นข้อความที่ตัดตอนมาเล็กน้อยซึ่งมีความเกี่ยวข้อง:

Self-interpreter เป็นล่ามภาษาโปรแกรมที่เขียนในภาษาโปรแกรมซึ่งสามารถตีความได้เอง ตัวอย่างคือล่ามพื้นฐานที่เขียนในภาษาเบสิก ตัวแปลภาษาเองเกี่ยวข้องกับคอมไพเลอร์ที่โฮสต์ด้วยตนเอง

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

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

แก้ไข. โปรดทราบว่าบทความวิกิพีเดียกล่าวอย่างชัดเจนว่าคุณต้องมีสองการดำเนินงานของภาษาของคุณและมันก็ไม่ได้บอกว่าคุณสามารถกำจัดแรก

ตอนนี้บทความที่กล่าวถึงด้านบนเชื่อมโยงไปยังบทความอื่นที่ Wikipedia ให้ตัวอย่างบางส่วนของล่ามที่โฮสต์ด้วยตนเอง เมื่อตรวจสอบอย่างใกล้ชิด แต่ดูเหมือนว่า "ล่าม" เป็นส่วนสำคัญของล่ามที่จัดการโฮสต์ด้วยตนเอง (โดยเฉพาะอย่างยิ่งภาษาทั่วไปเช่น PyPy หรือ Rubinius) ที่เขียนด้วยภาษาอื่นเช่น C ++ หรือ C

อีกครั้งถูกต้อง นี่เป็นตัวอย่างที่ไม่ดีจริงๆ ยกตัวอย่างเช่น Rubinius ใช่มันเป็นความจริงที่ส่วน Ruby ของ Rubinius เป็นโฮสต์ด้วยตัวเอง แต่เป็นคอมไพเลอร์ไม่ใช่ตัวแปล: มันรวมกับซอร์สโค้ด Ruby ถึง Rubinius bytecode OTOH ล่ามตอนนี้ไม่ได้เป็นโฮสต์โดยตัวมันเองแปลเป็น byteode ของ Rubinius แต่มันเขียนด้วยภาษา C ++ ดังนั้นการโทร Rubinius จึงเป็น "ล่ามที่โฮสต์โดยตนเอง" ผิด: ส่วนที่โฮสต์เองไม่ใช่ล่ามและส่วนล่ามไม่ได้โฮสต์เอง

PyPy คล้ายกัน แต่ยิ่งไม่ถูกต้อง: มันไม่ได้ถูกเขียนใน Python ตั้งแต่แรกมันเขียนด้วย RPython ซึ่งเป็นภาษาอื่น มันมีความคล้ายคลึงกับ Python syntactically, semantically เป็น "ส่วนย่อยที่ขยาย" แต่ที่จริงแล้วมันเป็นภาษาที่พิมพ์แบบสแตติกในระดับที่เป็นนามธรรมเช่นเดียวกับ Java และการใช้งานเป็นคอมไพเลอร์ที่มีแบ็กเอนด์หลายตัว ซอร์สโค้ด, โค้ดไบต์ CIL, JVM ไบต์, หรือซอร์สโค้ด Python

ดังนั้นสิ่งที่ฉันอธิบายข้างต้นเป็นไปได้? ล่าม Self-host นั้นสามารถเป็นอิสระจากโฮสต์เดิมได้หรือไม่? ถ้าเป็นเช่นนั้นจะทำเช่นนี้ได้อย่างไร?

ไม่ไม่ใช่ด้วยตัวเอง คุณอาจจำเป็นต้องใช้ล่ามดั้งเดิมหรือเขียนคอมไพเลอร์และรวบรวมล่ามของคุณเอง

มีเป็นบาง meta วงกลม VMs เช่นไคลน์ (เขียนเอง ) และแม็กซีน (เขียนใน Java) อย่างไรก็ตามโปรดทราบว่าที่นี่คำจำกัดความของ "meta-circular" นั้นแตกต่างกัน: VM เหล่านี้ไม่ได้เขียนในภาษาที่พวกเขาดำเนินการ: Klein เรียกใช้ Self bytecode แต่เขียนด้วยตนเอง Maxine เรียกใช้ JVM bytecode แต่เขียนด้วย Java อย่างไรก็ตามซอร์สโค้ด Self / Java ของ VM ได้รับการคอมไพล์ด้วย Self / JVM bytecode แล้วดำเนินการโดย VM ดังนั้นเมื่อถึงเวลาที่ VM ถูกเรียกใช้มันจะเป็นภาษาที่ดำเนินการ วุ้ย.

ยังทราบว่าเรื่องนี้จะแตกต่างจาก VMs เช่นSqueakVMและJikes RVM Jikes เขียนด้วยภาษาจาวาและ SqueakVM เขียนเป็นภาษาสแลง (เซตย่อยทางไวยากรณ์และความหมายที่พิมพ์แบบสแตติกของ Smalltalk โดยประมาณในระดับนามธรรมเดียวกันกับแอสเซมเบลอร์ระดับสูง) และทั้งสองได้รับการคอมไพล์ พวกเขาไม่ได้วิ่งเข้าไปข้างในตัวเอง อย่างไรก็ตามคุณสามารถเรียกใช้งานได้จากด้านบนของตัวเอง (หรือด้านบนของ Smalltalk VM / JVM อื่น) แต่นั่นไม่ใช่ "เมตาเวียน" ในแง่นี้

Maxine และ Klein, OTOH ทำทำงานภายในของตัวเอง พวกเขาดำเนินการ bytecode ของตัวเองโดยใช้การปฏิบัติ นี่คือความตั้งใจที่แท้จริง! อนุญาตให้มีโอกาสในการปรับให้เหมาะสมที่สุดเช่น VM ทำงานด้วยโปรแกรมผู้ใช้สามารถอินไลน์การโทรจากโปรแกรมผู้ใช้ไปยัง VM และในทางกลับกันเช่นการเรียกไปยังตัวรวบรวมขยะหรือตัวจัดสรรหน่วยความจำสามารถอินไลน์เข้าสู่ผู้ใช้ รหัสและการโทรกลับแบบไตร่ตรองในรหัสผู้ใช้สามารถถูกแทรกลงใน VM นอกจากนี้เทคนิคการทำให้เกิดประโยชน์สูงสุดอย่างชาญฉลาดที่ VMs ยุคใหม่ทำขึ้นโดยที่พวกเขาดูโปรแกรมการดำเนินการและปรับให้เหมาะสมขึ้นอยู่กับปริมาณงานและข้อมูลที่แท้จริง VM สามารถใช้เทคนิคเดียวกันเหล่านั้นกับตัวมันเอง กำลังดำเนินการเวิร์กโหลดเฉพาะ กล่าวอีกนัยหนึ่ง VM มีความเชี่ยวชาญสูงในเรื่องนั้นโปรแกรมเฉพาะการทำงานที่ภาระงานโดยเฉพาะอย่างยิ่ง

อย่างไรก็ตามโปรดสังเกตว่าฉันใช้คำว่า "ล่าม" ด้านบนและใช้ "ดำเนินการ" เสมอหรือไม่ ดีวีเอ็มเอสเหล่านั้นไม่ได้สร้างมาจากล่าม แต่ก็มีคอมไพเลอร์ในตัว (JIT) มีล่ามเพิ่มลงใน Maxine ในภายหลัง แต่คุณต้องการคอมไพเลอร์เสมอ: คุณต้องรัน VM หนึ่งครั้งบน VM อื่น (เช่น Oracle HotSpot ในกรณีของ Maxine) เพื่อให้ VM สามารถ (JIT) รวบรวมตัวเอง ในกรณีของ Maxine นั้น JIT จะทำการคอมไพล์เฟสบูทอัพของมันเองจากนั้นทำการเรียงลำดับโค้ดเนมที่คอมไพล์ให้กับอิมเมจ bootstrap VM และติดตั้งบูทโหลดเดอร์ที่เรียบง่ายไว้ข้างหน้า (ส่วนประกอบเดียวของ VM มันอาจจะเป็นใน Java ด้วย) ตอนนี้คุณสามารถใช้ Maxine เพื่อดำเนินการเองได้


เยช ฉันไม่เคยรู้ว่าโลกของการเป็นล่ามด้วยตนเองนั้นเหนียวเหนอะ! ขอบคุณที่ให้ภาพรวมที่ดี
Christian Dean

1
ฮ่าฮ่าทำไมทำไมโลกถึงต้องใจน้อยกว่าแนวคิด? ;-)
Jörg W Mittag

3
ฉันคิดว่าหนึ่งในปัญหาคือคนมักจะเล่นอย่างรวดเร็วและหลวมกับภาษาที่เกี่ยวข้อง ตัวอย่างเช่น Rubinius มักจะเรียกว่า "Ruby in Ruby" แต่นั่นเป็นเพียงครึ่งหนึ่งของเรื่องราว ใช่พูดอย่างเคร่งครัดคอมไพเลอร์ Ruby ใน Rubinius เขียนใน Ruby แต่ VM ซึ่งดำเนินการ bytecode ไม่ใช่ และยิ่งแย่กว่านั้น: PyPy มักถูกเรียกว่า "Python in Python" ยกเว้นว่าไม่มี Python ในบรรทัดเดียว สิ่งที่ทั้งถูกเขียนใน RPython ซึ่งถูกออกแบบมาให้คุ้นเคยกับโปรแกรมเมอร์หลาม แต่ไม่ได้เป็นงูหลาม SqueakVM ในทำนองเดียวกัน: มันไม่ได้เขียนใน Smalltalk มัน ...
Jörg W Mittag

... เขียนเป็นภาษาสแลงซึ่งอ้างอิงจากคนที่เข้ารหัสตามจริงแล้วยิ่งแย่กว่า C ในความสามารถที่เป็นนามธรรม คำสแลงที่มีประโยชน์อย่างเดียวคือมันเป็นเซตย่อยที่เหมาะสมของ Smalltalk ซึ่งหมายความว่าคุณสามารถพัฒนาได้ (และเรียกใช้และที่สำคัญที่สุดคือ debug VM บน) Smalltalk IDE อันทรงพลัง
Jörg W Mittag

2
เพียงเพื่อเพิ่มความซับซ้อนอื่น ๆ : บางภาษาที่แปล (เช่น FORTH และ TeX) สามารถเขียนอิมเมจหน่วยความจำที่โหลดได้ของระบบที่กำลังทำงานเป็นไฟล์ที่เรียกใช้งานได้ ในกรณีดังกล่าวระบบดังกล่าวสามารถทำงานได้โดยไม่ต้องใช้ตัวแปลต้นฉบับ ตัวอย่างเช่นฉันเคยเขียนล่าม FORTH โดยใช้ FORTH รุ่น 16 บิตเป็น "cross-translate" รุ่น 32 บิตสำหรับ CPU ที่แตกต่างกันและทำงานบนระบบปฏิบัติการอื่น (หมายเหตุภาษา FORTH รวมถึงแอสเซมเบลอร์ของตนเองดังนั้น "FORTH VM" (ซึ่งโดยทั่วไปจะมีเพียง 10 หรือ 20 คำสั่งรหัสเครื่อง) สามารถเขียนด้วย FORTH ได้)
alephzero

7

คุณถูกต้องในการสังเกตว่าล่ามที่โฮสต์ตัวเองยังคงต้องการล่ามเพื่อเรียกใช้ตัวเองและไม่สามารถ bootstrapped ในลักษณะเดียวกับคอมไพเลอร์

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

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

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

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

เมื่อมีการใช้ล่ามแปลภาษาที่ "จริง" ด้วยตนเองมักทำเพื่อเหตุผลทางการศึกษาหรือการวิจัย เช่นการใช้ล่ามสำหรับโครงการภายในโครงการเป็นวิธีที่ยอดเยี่ยมในการสอนภาษาโปรแกรม (ดู SICP)

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