กฎทั่วไปสำหรับการเขียนคอมไพเลอร์ X เป็น Z ใน Y


9

สมมติว่า X คือภาษาอินพุต Z คือภาษาเอาต์พุตจากนั้น f คือคอมไพเลอร์ซึ่งเขียนเป็นภาษา Y

f = X -> Z

เนื่องจาก f เป็นเพียงโปรแกรมฉันคิดว่า Y สามารถเป็นภาษาใด ๆ ใช่ไหม เราสามารถคอมไพล์เลอร์ f1, f2, แต่ละอันเขียนใน Y1, Y2

f1 = f Y1    
f2 = f Y2

g = Z -> M
h = g . f    # We get a compiler X -> M

ใช้คอมไพเลอร์ cpython เช่น X คือ Python, Z คือรหัส Python VM, Y คือ C

cpython = Python -> PythonVMCode C
interpreter = PythonVMCode -> Nothing
interpreter2 = PythonVMCode -> MachineCode

แหล่งไพ ธ อนถูกคอมไพล์กับรหัส Python VM ไฟล์. pyc จากนั้นตีความโดยล่าม ดูเหมือนว่ามีความเป็นไปได้ที่จะมีคอมไพเลอร์ซึ่งสามารถทำ Python -> MachineCode ได้โดยตรง แต่ก็ยากที่จะนำไปใช้:

   hardpython = interpreter2 . cpython 

นอกจากนี้เรายังสามารถเขียนคอมไพเลอร์ตัวอื่นทำผลงาน Python -> PythonVMCode ในภาษาอื่นพูด Python เอง

mypython = Python -> PythonVMCode Python
mypython2 = Python -> PythonVMCode Ruby

ตอนนี้นี่คือตัวอย่าง PyPy ที่ซับซ้อน ฉันเป็นมือใหม่ของ PyPy ให้แก้ไขฉันถ้าฉันผิด:

PyPy doc http://doc.pypy.org/en/latest/architecture.html#pypy-the-translation-framework

เป้าหมายของเราคือการจัดหาทางออกที่เป็นไปได้สำหรับปัญหาของผู้ใช้ภาษา: ต้องเขียนล่าม l * o * p สำหรับภาษา l ไดนามิกและแพลตฟอร์ม p ด้วยการตัดสินใจออกแบบที่สำคัญ

เราสามารถคิดว่า l คือ X, p คือ Y มีโปรแกรมที่แปลโปรแกรม RPython ทั้งหมดเป็น C:

 rpython_compiler = RPython -> C  Python

 pypy = Python -> Nothing RPython

 translate = compile the program pypy written in RPython using rpython_compiler

 py2rpy = Python -> RPython  Python
 py2c = Python -> C Python 
 py2c = rpython_compiler . py2rpy

โปรแกรม RPython เหมือนกับคำสั่ง VM, rpython_compiler คือ VM

q1 pypy คือ interpreter ซึ่งเป็นโปรแกรม RPython ที่สามารถแปลรหัส Python ได้ไม่มีภาษาเอาท์พุทดังนั้นเราจึงไม่สามารถถือว่ามันเป็นคอมไพเลอร์ใช่มั้ย

ที่เพิ่ม:

  • ฉันเพิ่งพบว่าแม้ว่าหลังจากการแปล Pypy ยังคงเป็นล่าม แต่คราวนี้เขียนเป็น C เท่านั้น
  • หากเรามองลึกลงไปใน pypy ล่ามฉันเชื่อว่าต้องมีคอมไพเลอร์บางชนิดซึ่งรวบรวมไพทอนแหล่งที่มากับ AST บางตัวจากนั้นดำเนินการ

แบบนี้:

compiler_inside_pypy = Python -> AST_or_so

q2 คอมไพเลอร์ py2rpy มีอยู่สามารถแปลงโปรแกรม Python ทั้งหมดเป็น RPython ได้หรือไม่ ภาษาที่ใช้เขียนนั้นไม่เกี่ยวข้อง ถ้าใช่เราได้รับ py2c คอมไพเลอร์อื่น ความแตกต่างระหว่าง pypy และ py2rpy ในธรรมชาติคืออะไร? py2rpy เขียนยากกว่า pypy หรือไม่?

q3 มีกฎหรือทฤษฎีทั่วไปเกี่ยวกับเรื่องนี้หรือไม่?

คอมไพเลอร์เพิ่มเติม:

gcc_c = C -> asm? C  # not sure, gimple or rtl?
g++ =   C++ -> asm? C
clang = C -> LLVM_IR  C++
jython = Python -> JVMCode java
ironpython = Python -> CLI C#

q4 รับ f = X -> Z โปรแกรม P ที่เขียนด้วย X เมื่อเราต้องการเร่งความเร็ว P เราจะทำอะไรได้บ้าง วิธี Possbile:

  • เขียน P ใหม่ในอัลกอริทึมที่มีประสิทธิภาพมากขึ้น

  • เขียน f เพื่อสร้าง Z ที่ดีกว่า

  • ถ้า Z ถูกตีความให้เขียนล่าม Z ที่ดีกว่า (PyPy อยู่ที่นี่?)

  • เร่งความเร็วโปรแกรมที่เขียนด้วย Z แบบวนซ้ำ

  • รับเครื่องที่ดีกว่า

PS คำถามนี้ไม่ได้เกี่ยวกับเทคโนโลยีของวิธีการเขียนคอมไพเลอร์ แต่ความเป็นไปได้และความซับซ้อนของการเขียนคอมไพเลอร์ชนิดหนึ่ง


ไม่เกี่ยวข้องโดยตรง แต่เป็นแนวคิดที่คล้ายกัน: en.wikipedia.org/wiki/Supercompilation
SK-logic

1
ฉันไม่แน่ใจว่าคำถามนี้เหมาะกับ Stack Overflow โดยเฉพาะอย่างยิ่งเนื่องจากมีคำถามย่อยมากมายในนั้น แต่ฉันก็ยังชื่นชมความคิดที่เข้ามาเกี่ยวข้อง

4
แม้จะมีสิ่งที่คุณได้รับการสอน แต่ก็ไม่จำเป็นต้องใช้ AST - เป็นเพียงกลยุทธ์ที่คอมไพเลอร์ใช้

1
อาจเป็นของ cstheory.stackexchange.com
9000

3
การใช้งาน Python ของ PyPy เช่น "ล่าม" ส่วนใหญ่เป็นคอมไพเลอร์ bytecode และล่ามสำหรับรูปแบบ bytecode นั้นในหนึ่งเดียว

คำตอบ:


4

q1 pypy คือ interpreter ซึ่งเป็นโปรแกรม RPython ที่สามารถแปลรหัส Python ได้ไม่มีภาษาเอาท์พุทดังนั้นเราจึงไม่สามารถถือว่ามันเป็นคอมไพเลอร์ใช่มั้ย

PyPy คล้ายกับ CPython ทั้งคู่มีคอมไพเลอร์ + ล่าม CPython มีคอมไพเลอร์เขียนใน C ที่รวบรวม Python ถึง Python VM bytecode จากนั้นดำเนินการ bytecode ในล่ามที่เขียนใน C. PyPy มีคอมไพเลอร์ที่เขียนใน RPython ที่รวบรวม Python ไปยัง Python VM bytecode แล้วดำเนินการใน PyPy Interpreter

q2 คอมไพเลอร์ py2rpy มีอยู่สามารถแปลงโปรแกรม Python ทั้งหมดเป็น RPython ได้หรือไม่ ภาษาที่ใช้เขียนนั้นไม่เกี่ยวข้อง ถ้าใช่เราได้รับ py2c คอมไพเลอร์อื่น ความแตกต่างระหว่าง pypy และ py2rpy ในธรรมชาติคืออะไร? py2rpy เขียนยากกว่า pypy หรือไม่?

คอมไพเลอร์ py2rpy สามารถมีอยู่ได้หรือไม่? ในทางทฤษฎีใช่ ทัวริงสมบูรณ์รับประกันดังนั้น

วิธีหนึ่งในการสร้างpy2rpyคือการรวมซอร์สโค้ดของล่าม Python ที่เขียนใน RPython ในซอร์สโค้ดที่สร้างขึ้น ตัวอย่างของคอมไพเลอร์ py2rpy เขียนใน Bash:

// suppose that /pypy/source/ contains the source code for pypy (i.e. Python -> Nothing RPython)
cp /pypy/source/ /tmp/py2rpy/pypy/

// suppose $inputfile contains an arbitrary Python source code
cp $inputfile /tmp/py2rpy/prog.py

// generate the main.rpy
echo "import pypy; pypy.execfile('prog.py')" > /tmp/py2rpy/main.rpy

cp /tmp/py2rpy/ $outputdir

ตอนนี้เมื่อใดก็ตามที่คุณต้องการแปลรหัส Python เป็นรหัส RPython คุณเรียกสคริปต์นี้ซึ่งสร้าง - ใน $ outputdir - RPython main.rpy, ซอร์สโค้ด Python Interpreter ของ RPython และไบนารี prog.py blob และจากนั้นคุณสามารถรันสคริปต์ RPython rpython main.rpyสร้างขึ้นโดยการเรียก

(หมายเหตุ: เนื่องจากฉันไม่คุ้นเคยกับโครงการ rpython ไวยากรณ์สำหรับการโทรหา rpython interpreter ความสามารถในการนำเข้า pypy และ pypy.execfile และส่วนขยาย. rpy ถูกสร้างขึ้นอย่างหมดจด แต่ฉันคิดว่าคุณเข้าใจแล้ว)

q3 มีกฎหรือทฤษฎีทั่วไปเกี่ยวกับเรื่องนี้หรือไม่?

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

q4 ...

ไม่มีคำถามอยู่ที่นี่


คอมไพเลอร์ py2rpy ของคุณฉลาดจริงๆ มันทำให้ฉันมีความคิดอื่น 1. ต้องมีการเขียน pypy ใน RPython ในคอมไพเลอร์ของคุณหรือไม่? สิ่งที่คุณต้องการคือสิ่งที่สามารถตีความไฟล์ Python ได้ใช่ไหม 2. os.system ('python $ inputfile') อาจใช้งานได้หากสนับสนุนใน RPython ไม่แน่ใจว่ายังสามารถเรียกใช้คอมไพเลอร์ได้หรือไม่

pypy ยังใช้ Python VM อยู่หรือไม่ ตอนนี้มันชัดเจน pypy_the_compiler = Python -> PythonVMCode RPython, pypy_the_interpreter = PythonVMCode -> ไม่มีอะไร RPython, cpython_the_compiler = Python -> PythonVMCode C, cpython_the_interpreter = PythonVMCode -> ไม่มีอะไร C

@jaimechen: Does pypy have to be written in RPython in your compiler?ไม่มันไม่จำเป็นต้องเขียนใน RPython แต่ RPython จะต้องสามารถบอก "interpreter ช่วย" / "รันไทม์" เพื่อรันรหัส Python ใช่มันเป็นความจริงนี้ไม่ได้เป็น "คอมไพเลอร์" ในแง่การปฏิบัติ Python -> RPythonแต่มันเป็นหลักฐานที่สร้างสรรค์ว่ามันเป็นไปได้ที่จะเขียน Is pypy still using the Python VM?ฉันเชื่อว่า pypy ไม่ได้ใช้ CPython เลย (อาจผิด) แทน PyPy มีการใช้งาน "Python VM" ของตัวเองซึ่งเขียนใน RPython
Lie Ryan

@jaimechen: คอมไพเลอร์ที่ใช้งานได้จริงมากขึ้นสามารถวิเคราะห์ไฟล์อินพุตสำหรับลำดับของรหัสที่รู้วิธีรวบรวมและคอมไพล์เหล่านี้แยกกันและวิธีการข้ามไปมาระหว่าง Python "recompiled-to-RPython" และ interpreter- ช่วย "Python นอกจากนี้ยังอาจใช้เทคนิคที่ใช้กันทั่วไปในการรวบรวม JIT เพื่อตรวจสอบว่าอินพุตเฉพาะอาจสร้างเอาต์พุตที่แตกต่างกันเนื่องจากความแตกต่างในความหมายของ RPython และ Python และทางเลือกในการตีความในกรณีเหล่านั้น ทั้งหมดนี้เป็นความซับซ้อนที่อาจเห็นได้ในPython -> RPythonคอมไพเลอร์ที่ใช้งานได้จริง
Lie Ryan

อาจเพิ่มข้อ จำกัด ได้ที่นี่: เปลี่ยนสถานะเครื่อง X เป็นสถานะเครื่องจักร Z โดยไม่ต้องใช้เครื่องที่ 3 ที่มีอยู่ นี่เป็นกรณีที่ X เป็นสิ่งใหม่ทั้งหมดไม่มีผู้แปลหรือล่ามอยู่เลย
jaimechen

2

เพื่อตอบคำถาม q2 เท่านั้นมีหนังสือรวบรวมโดยวิลเลียมแมคเคอแมนซึ่งทฤษฎีของคอมไพเลอร์สำหรับภาษา X ที่เขียนในภาษา Y ที่ผลิตภาษาเอาท์พุท Z ถูกสำรวจผ่านระบบ T-diagrams ตีพิมพ์ในปี 1970 ชื่อไม่ถึงมือขอโทษ


ใช่มันเป็นเช่นนั้นขอบคุณ en.wikipedia.org/wiki/Tombstone_diagram
jaimechen

1

q1 โดยทั่วไปแล้วล่ามไม่ใช่ผู้แปล ความแตกต่างที่สำคัญระหว่างคอมไพเลอร์และล่ามคือล่ามเริ่มใหม่โดยมีซอร์สโค้ดในภาษาต้นฉบับทุกครั้ง ถ้า pypy ของคุณเป็น pyast แทนหรือ pyP-code จากนั้นคุณมี AST หรือ P-code interpreter คุณก็สามารถเรียก pyast คอมไพเลอร์ได้ นี่คือวิธีที่คอมไพเลอร์ UCSD PASCAL รุ่นเก่าทำงาน (รวมถึงบางตัว): พวกเขาคอมไพล์รหัส P-code บางตัวซึ่งถูกตีความเมื่อโปรแกรมทำงาน (แม้แต่. NET จะให้อะไรเช่นนี้เมื่อความกะทัดรัดของรหัสวัตถุที่สร้างมีความสำคัญมากกว่าความเร็ว)

q2 ใช่แน่นอน ดู UCSD PASCAL (และอื่น ๆ อีกมากมาย)

q3 ขุดผ่านข้อความคลาสสิกในวิทยาการคอมพิวเตอร์ อ่านค่า PASCAL ที่เกิดขึ้นพร้อมกันโดย Per Brinch-Hansen (ถ้าหน่วยความจำทำหน้าที่ฉัน) มีการเขียนมากมายเกี่ยวกับคอมไพเลอร์และการสร้างรหัส การสร้าง pseudocode ที่ไม่ขึ้นกับเครื่องจักรนั้นมักจะง่ายกว่าการสร้างรหัสเครื่อง: pseudocode นั้นมักจะปราศจากความผิดปกติที่เครื่องของเรามีอยู่จริง

q4 ถ้าคุณต้องการให้วัตถุที่สร้างขึ้นของคุณทำงานได้เร็วขึ้นคุณต้องทำให้คอมไพเลอร์ฉลาดขึ้นเพื่อเพิ่มประสิทธิภาพให้ดียิ่งขึ้น หากวัตถุของคุณถูกตีความคุณพิจารณาผลักดันการดำเนินงานที่ซับซ้อนมากขึ้นลงใน pseudoinstructions ดั้งเดิม (CISC เทียบกับ RISC เป็นการเปรียบเทียบ) จากนั้นคุณทำอย่างดีที่สุดเพื่อเพิ่มประสิทธิภาพ frack จากล่ามของคุณ

หากคุณต้องการให้คอมไพเลอร์ทำงานได้เร็วขึ้นคุณต้องดูทุกอย่างที่ทำได้รวมถึงการทบทวนซอร์สโค้ดของคุณใหม่ หลังจากโหลดคอมไพเลอร์ของตัวเองส่วนใหญ่ใช้เวลานานในการรวบรวมเป็นเสมออ่านรหัสที่มาลงในคอมไพเลอร์ (ลองพิจารณา C ++ เช่นกันสิ่งอื่น ๆ ทั้งหมดนั้นค่อนข้างเท่าเทียมกันคอมไพเลอร์ที่จะต้องตัดทอนบรรทัด #include จำนวน 9,000 บรรทัด (หรืออาจจะ 50,000 บรรทัด) เพื่อคอมไพล์โปรแกรม "Hello, World" ที่เรียบง่ายจะไม่เร็วเท่ากับหนึ่ง ที่มีเพียงการอ่านสี่หรือห้าบรรทัด)

ฉันจำไม่ได้ว่าอ่านตรงไหน แต่คอมไพเลอร์ Oberon ดั้งเดิมที่ ETH-Zurich มีกลไกตารางสัญลักษณ์ที่ซับซ้อนมาก ๆ มาตรฐานของ Wirth สำหรับประสิทธิภาพของคอมไพเลอร์คือเวลาที่คอมไพเลอร์รวบรวมตัวเอง เช้าวันหนึ่งเขาเข้าไปข้างในดึงตารางสัญลักษณ์อัลตร้าทรีที่เชื่อมโยงหลายพันอันงดงามเอาไว้และแทนที่มันด้วยอาร์เรย์แบบเส้นตรงและการค้นหาแบบเส้นตรง นักศึกษาระดับบัณฑิตศึกษาในกลุ่มของเขาตกใจ หลังจากการเปลี่ยนแปลงคอมไพเลอร์ก็เร็วขึ้นเพราะโมดูลที่รวบรวมนั้นเล็กพอที่มอนสเตอร์ที่สง่างามจะกำหนดค่าใช้จ่ายทั้งหมดมากกว่าอาร์เรย์เชิงเส้นและการค้นหาเชิงเส้น


1
ขอบคุณ คอมไพเลอร์ 'คอมไพเลอร์' ในขณะที่ผู้แปลทำการประมวลผลจะมีความเข้าใจที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับโปรแกรมทั้งสองประเภทเช่นประเภทของพวกเขาแตกต่างกันหรือไม่?
jaimechen

1

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

คอมไพเลอร์แมปโปรแกรมที่เขียนด้วยภาษา X กับโปรแกรมที่เทียบเท่ากับการใช้งานที่เขียนในภาษา Y ตัวอย่างเช่นคอมไพเลอร์จาก Pascal ถึง C อาจรวบรวม

function Square(i: Integer)
begin
    Square := i * i
end

ถึง

int Square(int i)
{
    return i * i;
}

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

คอมไพเลอร์ส่วนใหญ่คอมไพล์โดยตรงกับรหัสเครื่อง แต่บางภาษา (โดยเฉพาะภาษาจาวาและภาษา. NET) จะคอมไพล์เป็น 'bytecode' ( Java bytecodeและCIL ) คิดว่า bytecode เป็นรหัสเครื่องสำหรับคอมพิวเตอร์สมมุติ โค้ดไบต์นี้จะถูกตีความหรือ JITted เมื่อมันถูกเรียกใช้ (เพิ่มเติมในภายหลัง)

ล่ามดำเนินการโปรแกรมที่เขียนในบางภาษา Z. ล่ามอ่านโปรแกรมทีละบิตดำเนินการตามที่มันไป ตัวอย่างเช่น

int i = 0;
while (i < 1)
{
    i++
}
return i;

ลองจินตนาการว่าล่ามกำลังดูบรรทัดของโปรแกรมนั้นตรวจสอบบรรทัดดำเนินการสิ่งที่ทำดูที่บรรทัดถัดไปเป็นต้น

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

JITterเป็นคอมไพเลอร์ Just-In-Time JITter เป็นคอมไพเลอร์ ความแตกต่างเพียงอย่างเดียวคือเวลาที่ใช้งาน: โปรแกรมส่วนใหญ่เขียนรวบรวมส่งไปยังผู้ใช้แล้วดำเนินการ แต่ Java bytecode และ CIL ถูกส่งไปยังผู้ใช้ก่อนจากนั้นก่อนที่จะถูกประมวลผลจะถูกรวบรวมไปยังเครื่อง รหัสของผู้ใช้

C # -> (คอมไพล์) -> CIL -> ส่งไปยังลูกค้า -> (คอมไพล์ก่อนดำเนินการ) -> รหัสเครื่อง -> (ดำเนินการ)

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

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

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

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