C ++: Metaprogramming ด้วย API คอมไพเลอร์มากกว่าด้วยคุณสมบัติ C ++


10

สิ่งนี้เริ่มต้นจากคำถาม SO แต่ฉันรู้ว่ามันค่อนข้างแปลกใหม่และตามคำอธิบายที่แท้จริงบนเว็บไซต์มันอาจจะเหมาะกว่าสำหรับ programmers.se เนื่องจากคำถามมีน้ำหนักเชิงแนวคิดจำนวนมาก

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

ตอนนี้ให้ฉันถอยกลับสักครู่

มีปัญหาในทางปฏิบัติมากมายที่เกิดขึ้นเมื่อมีคนเข้าร่วมในเทมเพลต metaprogramming เทมเพลต C ++ (และโดยเฉพาะอย่างยิ่งเมื่อมีการใช้เทมเพลตเกินกว่าเทมเพลตเข้าไปในอาณาเขตของมาโครที่ชาญฉลาด ตามจริงแล้วสำหรับโปรแกรมเมอร์หลาย ๆ คนรวมถึงตัวเองการใช้งานเทมเพลตทั่วไปจำนวนมากก็ค่อนข้างน่ากลัวเช่นกัน

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

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

ป้อน clang และ LibTooling ซึ่งแสดงแผนผังต้นไม้นามธรรม (AST) ของซอร์สโค้ดและอนุญาตให้แอปพลิเคชัน C ++ แบบกำหนดเองอย่างง่าย ๆ สามารถจัดการกับซอร์สโค้ดดิบ (ใช้Rewriter) อย่างถูกต้องและเชื่อถือได้พร้อมกับโมเดลเชิงวัตถุเชิงความหมาย มันจัดการกับสิ่งต่าง ๆ มากมาย มันรู้เกี่ยวกับการขยายมาโครและช่วยให้คุณติดตามกลุ่มเหล่านั้นได้ ใช่ฉันกำลังพูดถึงการแปลงหรือการแปลซอร์สโค้ด

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

การป้อนข้อมูลจะต้องใกล้เคียงกับรหัส C ++ ที่ถูกต้องอย่างน้อยที่สุดเพราะหลังจากนั้นเสียงดังกราวคือคอมไพเลอร์ฟรอนต์เอนด์และเราเพียงแค่พูดเล่น ๆ และสร้างสรรค์ด้วย API ของมัน ฉันไม่ทราบว่ามีข้อกำหนดใด ๆ สำหรับความสามารถในการกำหนดไวยากรณ์ใหม่ที่จะใช้ แต่ชัดเจนว่าเราต้องพัฒนาวิธีในการแยกวิเคราะห์อย่างถูกต้องและเพิ่มลงในโครงการเสียงดังกราวเพื่อทำสิ่งนี้ การคาดหวังอีกต่อไปคือการมีบางสิ่งในโครงการเสียงดังกราวที่อยู่นอกขอบเขต

ไม่ใช่ปัญหา. ฉันนึกภาพว่าฟังก์ชั่นมาโครที่ไม่มี op บางตัวสามารถจัดการงานนี้ได้

อีกวิธีหนึ่งในการดูสิ่งที่ฉันอธิบายคือการนำ metaprogramming constructs ไปใช้โดยใช้ runtime C ++ ด้วยการจัดการ AST ของซอร์สโค้ดของเรา (ขอบคุณ clang และ API) แทนที่จะใช้มันโดยใช้เครื่องมือที่ จำกัด มากขึ้นในภาษาของตัวเอง สิ่งนี้มีประโยชน์ด้านประสิทธิภาพการคอมไพล์ที่ชัดเจนเช่นกัน (ส่วนหัวเทมเพลต - หนักการรวบรวมช้าลงตามสัดส่วนที่คุณใช้บ่อย ๆ สิ่งที่รวบรวมไว้จำนวนมากจากนั้นจะถูกจับคู่อย่างระมัดระวังและทิ้งโดยลิงเกอร์)

อย่างไรก็ตามสิ่งนี้มีค่าใช้จ่ายในการแนะนำขั้นตอนเพิ่มเติมหรือสองขั้นตอนในกระบวนการสร้างและในความต้องการของการเขียนซอฟต์แวร์ verbose ค่อนข้างมาก (เป็นที่ยอมรับ) (อย่างน้อยก็ตรงไปตรงมา runtime C ++) เป็นส่วนหนึ่งของเครื่องมือของเรา .

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

ดังนั้นฉันสงสัยว่าทำไมทุกคนไม่ได้ทำเช่นนี้ ฟังก์ชั่นนี้จาก clang นั้นใหม่และไม่มีใครคุ้นเคยกับ AST ของ clang ในระดับชั้นเรียนขนาดใหญ่? ไม่สามารถทำได้

บางทีฉันอาจจะประเมินความยากของเรื่องนี้เล็กน้อย แต่การทำ "การจัดการสตริงเวลารวบรวม" ด้วยเครื่องมือเสียงดังกราวอาจเป็นเรื่องง่าย มัน verbose แต่ตรงไปตรงมาเมามัน สิ่งที่จำเป็นทั้งหมดคือฟังก์ชั่นมาโครที่ไม่ต้องใช้งานซึ่งแมปกับstd::stringการใช้งานจริง ปลั๊กอินเสียงดังกราวใช้ส่วนนี้โดยดึงมาโครที่ไม่มีการเรียกแมโครที่เกี่ยวข้องทั้งหมดและทำการดำเนินการกับสตริง เครื่องมือนี้จะถูกแทรกเป็นส่วนหนึ่งของกระบวนการสร้าง ในระหว่างการสร้างการเรียกฟังก์ชันแมโคร no-op เหล่านี้จะถูกประเมินโดยอัตโนมัติในผลลัพธ์แล้วแทรกกลับเป็นสตริงการคอมไพล์เวลาเก่าแบบธรรมดาในโปรแกรม โปรแกรมสามารถคอมไพล์ได้ตามปกติ ในความเป็นจริงโปรแกรมที่เป็นผลลัพธ์นี้ยังพกพาได้มากขึ้นโดยไม่ต้องใช้คอมไพเลอร์ตัวใหม่ที่รองรับ C ++ 11


นี่เป็นคำถามที่ยาวผิดปกติ บางทีคุณอาจย่อมันไปยังจุดที่เกี่ยวข้องมากที่สุดของคุณ?
amon

ฉันโพสต์คำถามยาว ๆ มากมาย แต่โดยเฉพาะอย่างยิ่งกับสิ่งนี้ทุกส่วนของคำถามมีความสำคัญฉันคิดว่า อาจข้าม 6 ย่อหน้าแรกไปใช่ไหม ฮ่าฮ่า
Steven Lu

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

ใช่ meta-ifying C ++ ซึ่งอาจหมายถึงรหัสที่ดีกว่าและเร็วกว่า สำหรับภาษาเหล่านั้น ฉันจะเริ่มจากตรงไหนดี วิดีโอเกมที่มีมูลค่าหลายล้านดอลล่าร์นำมาใช้ในภาษาเหล่านั้นคืออะไร เว็บเบราว์เซอร์ที่ทันสมัยมีการใช้งานในภาษาใดบ้าง เคอร์เนลระบบปฏิบัติการ เอาล่ะดูเหมือนว่า Haxe มีแรงฉุดบ้าง แต่คุณก็เข้าใจ
Steven Lu

1
@nwp ดีฉันอดไม่ได้ที่จะชี้ให้เห็นว่าคุณพลาดจุดโพสต์ทั้งหมดแล้ว สตริงการรวบรวมเวลาเป็นเพียงตัวอย่างที่ชัดเจนที่สุดของความสามารถที่เรามีในขณะนี้
Steven Lu

คำตอบ:


7

ใช่เวอร์จิเนียมีซานตาคลอสอยู่

แนวคิดของการใช้โปรแกรมเพื่อปรับเปลี่ยนโปรแกรมต่าง ๆ มีมานานแล้ว แนวคิดดั้งเดิมมาจากJohn von Neumannในรูปแบบของโปรแกรมคอมพิวเตอร์ที่เก็บไว้ แต่การแก้ไขรหัสเครื่องในลักษณะที่เป็นการสุ่มนั้นไม่สะดวก

คนทั่วไปต้องการปรับเปลี่ยนแหล่งรหัส นี้จะรู้ส่วนใหญ่อยู่ในรูปแบบของระบบการเปลี่ยนแปลงโปรแกรม (PTS)

โดยทั่วไปแล้วข้อเสนอ PTS สำหรับภาษาการเขียนโปรแกรมอย่างน้อยหนึ่งภาษาความสามารถในการวิเคราะห์ AST จัดการกับ AST นั้นและสร้างข้อความต้นฉบับที่ถูกต้องขึ้นมาใหม่ หากในความเป็นจริงคุณขุดหาภาษาหลักส่วนใหญ่บางคนได้สร้างเครื่องมือดังกล่าว (Clang เป็นตัวอย่างสำหรับ C ++, คอมไพเลอร์ Java มีความสามารถนี้เป็น API, Microsoft เสนอ Rosyln, JDT ของ Eclipse ของ Eclipse) API ที่มีประโยชน์จริง ๆ สำหรับชุมชนที่กว้างขึ้นชุมชนชุมชนที่มีภาษาเฉพาะเกือบทุกภาษาสามารถชี้ไปที่สิ่งนี้ได้ดำเนินการโดยมีวุฒิภาวะในระดับต่าง ๆ (โดยทั่วไปแล้วจะค่อนข้างเรียบง่าย มีความสุข metaprogramming

[มีชุมชนที่มุ่งเน้นการสะท้อนซึ่งพยายามทำ metaprogramming จากภายในภาษาการเขียนโปรแกรม แต่ให้บรรลุการปรับเปลี่ยนพฤติกรรม "รันไทม์" และเฉพาะในกรณีที่คอมไพเลอร์ภาษาทำให้ข้อมูลบางอย่างสะท้อน ด้วยข้อยกเว้นของ LISP จะมีรายละเอียดเกี่ยวกับโปรแกรมที่ไม่สามารถใช้การสะท้อนได้ ("ลุคคุณต้องใช้แหล่งที่มา") ที่ จำกัด การสะท้อนที่สามารถทำได้]

PTS ที่น่าสนใจยิ่งขึ้นทำเช่นนี้สำหรับภาษาที่กำหนดเอง (คุณให้คำอธิบายภาษาเป็นพารามิเตอร์การกำหนดค่าเครื่องมือรวมถึง BNF ขั้นต่ำ) PTS ดังกล่าวยังช่วยให้คุณทำการแปลง "แหล่งสู่แหล่งที่มา" เช่นระบุรูปแบบโดยตรงโดยใช้ไวยากรณ์พื้นผิวของภาษาเป้าหมาย ใช้รูปแบบดังกล่าวคุณสามารถโค้ดส่วนที่น่าสนใจและ / หรือค้นหาและแทนที่ชิ้นส่วนรหัส นี่สะดวกกว่าการเขียนโปรแกรม API เนื่องจากคุณไม่จำเป็นต้องทราบรายละเอียดทุกอย่างเกี่ยวกับ AST เพื่อทำงานส่วนใหญ่ของคุณ คิดว่านี่เป็น meta-metaprogramming: -}

ข้อเสีย: นอกจาก PTS จะเสนอการวิเคราะห์แบบสแตติกที่มีประโยชน์หลายชนิด (ตารางสัญลักษณ์การควบคุมและการวิเคราะห์การไหลของข้อมูล) มันยากที่จะเขียนการแปลงที่น่าสนใจจริงๆด้วยวิธีนี้เพราะคุณต้องตรวจสอบประเภทและตรวจสอบกระแสข้อมูล น่าเสียดายที่ความสามารถนี้มีอยู่จริงใน PTS ทั่วไป (มันไม่สามารถใช้งานได้กับข้อเสนอที่เคย "ถ้าฉันมี parser ... " ดูประวัติของฉันสำหรับการอภิปรายอีกต่อไปของ "Life After Parsing")

มีทฤษฏีที่บอกว่าถ้าคุณสามารถเขียนสตริงได้ [ดังนั้นการเขียนใหม่ต้นไม้] คุณสามารถทำการแปลงโดยพลการได้ และด้วยเหตุนี้จำนวน PTS จึงพึ่งพาสิ่งนี้เพื่ออ้างว่าคุณสามารถ metaprogram อะไรก็ได้ที่มีเพียงต้นไม้ที่พวกเขาเขียนใหม่ ในขณะที่ทฤษฏีนั้นพอใจในแง่ที่คุณมั่นใจว่าคุณสามารถทำอะไรได้มันก็ไม่เป็นที่พอใจเช่นเดียวกับที่ความสามารถของทัวริงในการทำทุกอย่างไม่ได้ทำให้การโปรแกรม Turing Machine เป็นทางเลือก (เช่นเดียวกันถือเป็นจริงสำหรับระบบที่มี API แบบขั้นตอนเพียงอย่างเดียวหากพวกเขาจะให้คุณทำการเปลี่ยนแปลงโดยพลการต่อ AST [และอันที่จริงฉันคิดว่านี่ไม่ใช่ความจริงของ Clang])

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

  • ภาษาโปรแกรมการเขียนโปรแกรม Rascal (MPL)
  • ชุดเครื่องมือการปรับรื้อซอฟต์แวร์ DMS ของเรา

ถ้าคุณไม่ต้องการเขียนคำอธิบายภาษาและตัววิเคราะห์แบบสแตติกด้วยตัวเอง (สำหรับ C ++ นี่เป็นจำนวนมากของการทำงานซึ่งเป็นสาเหตุที่เสียงดังกราวถูกสร้างขึ้นทั้งในฐานะคอมไพเลอร์และพื้นฐานพื้นฐานของ metaprogramming) คุณจะต้องการ PTS มีอยู่แล้ว มิฉะนั้นคุณจะใช้เวลาทั้งหมดในการกำหนดค่า PTS และไม่มีใครทำงานที่คุณอยากทำ [หากคุณเลือกภาษาแบบสุ่มและไม่สำคัญขั้นตอนนี้ยากที่จะหลีกเลี่ยง]

Rascal พยายามทำสิ่งนี้ด้วยการเลือก "OPP" (ตัวแยกวิเคราะห์ของผู้อื่น) แต่ไม่ช่วยในส่วนการวิเคราะห์แบบคงที่ ฉันคิดว่าพวกเขามี Java อยู่ในมือค่อนข้างดี แต่ฉันแน่ใจว่าพวกเขาไม่ได้ทำ C หรือ C ++ แต่มันเป็นเครื่องมือวิจัยทางวิชาการ ยากที่จะตำหนิพวกเขา

ฉันเน้นเครื่องมือ DMS [โฆษณา] ของเรามี Java, C, C ++ เต็มรูปแบบให้ใช้ สำหรับ C ++ นั้นครอบคลุมเกือบทุกอย่างใน C ++ 14 สำหรับ GCC และแม้แต่การเปลี่ยนแปลงของ Microsoft (และเรากำลังปรับปรุงอยู่ในขณะนี้) การขยายแมโครและการจัดการตามเงื่อนไขและการควบคุมระดับวิธีและการวิเคราะห์การไหลของข้อมูล และใช่คุณสามารถระบุการเปลี่ยนแปลงทางไวยากรณ์ในทางปฏิบัติ; เราสร้างระบบ VectorC ++ ที่กำหนดเองสำหรับลูกค้าที่ขยาย C ++ อย่างรุนแรงเพื่อใช้จำนวนเท่าใดสำหรับการดำเนินการอาร์เรย์ข้อมูลแบบขนาน F90 / APL DMS ถูกนำมาใช้เพื่อดำเนินงาน metaprogramming ขนาดใหญ่อื่น ๆ ในระบบ C ++ ขนาดใหญ่ (เช่นการปรับแต่งสถาปัตยกรรมแอปพลิเคชัน) (ฉันเป็นสถาปนิกด้านหลัง DMS)

มีความสุข meta-metaprogramming


เจ๋งฉันคิดว่า Clang และ DMS ในขณะที่พวกเขามีความสามารถที่ทับซ้อนกันเป็นชิ้นส่วนของซอฟต์แวร์ที่ไม่ได้อยู่ในหมวดหมู่เดียวกัน ฉันหมายความว่าอย่างใดอย่างหนึ่งอาจมีราคาแพงขันและฉันอาจไม่สามารถพิสูจน์ทรัพยากรที่ต้องใช้เพื่อเข้าถึงและอื่น ๆ เป็นโอเพนซอร์สฟรีไม่ จำกัด นี่คือความแตกต่างอย่างมาก ... ส่วนหนึ่งของสิ่งที่ทำให้ฉันตื่นเต้นเกี่ยวกับความสามารถในการ metaprogramming ที่น่าตื่นเต้นเหล่านี้เป็นความจริงที่ว่าไม่เพียง แต่อนุญาตให้ใช้อย่างอิสระเท่านั้น แต่ยังแจกจ่ายเครื่องมือไบนารีที่ใช้เสียงดัง
Steven Lu

สิ่งที่ขายในเชิงพาณิชย์คือ "แพงซ้ำซาก" เมื่อเทียบกับฟรี ต้นทุนดิบไม่ใช่ปัญหา สิ่งที่สำคัญคือสำหรับบางคนการคืนทุนสำหรับการซื้อผลิตภัณฑ์เชิงพาณิชย์นั้นสูงกว่าการคืนทุนสำหรับสิ่งประดิษฐ์ฟรีมิฉะนั้นจะไม่มีซอฟต์แวร์เชิงพาณิชย์ ชัดเจนขึ้นอยู่กับความต้องการเฉพาะของคุณ เสียงดังกราวเป็นจุดที่น่าสนใจในพื้นที่เครื่องมือและจะมีจุดของการใช้งานที่มีประโยชน์อย่างแน่นอน ฉันต้องการคิด (เนื่องจากฉันเป็นสถาปนิก DMS) ที่ DMS มีความสามารถที่กว้างขึ้น เสียงดังกังวานไม่สนับสนุนภาษาอื่นที่ไม่ใช่ภาษาซีพลัสพลัสเช่น
Ira Baxter

อย่างแน่นอน ไม่มีคำถามที่ว่า DMS นั้นมีพลังอย่างไม่น่าเชื่อเกือบถึงจุดมหัศจรรย์ (à la Arthur C. Clarke) และในขณะที่เสียงดังกราวนั้นยอดเยี่ยมจริงๆมันเป็นเพียงส่วนหน้าของ C ++ ที่เขียนขึ้นอย่างดี ก้าวต่อไปเล็ก ๆ น้อย ๆ ที่ยอดเยี่ยมนั่นคือมันยังคงไม่ยุติธรรมเลยที่จะเปรียบเทียบกับ DMS อนิจจาแม้จะมีเครื่องมือที่ทรงพลังเช่นนี้ในการกำจัดของเราซอฟต์แวร์ที่ใช้งานได้ไม่ได้เขียนเอง มันจะต้องยังคงมีอยู่ผ่านการแปลอย่างระมัดระวังโดยใช้เครื่องมือหรือ (ตัวเลือกที่ดีกว่าเสมอ) เขียนสด
Steven Lu

คุณไม่สามารถสร้างเครื่องมือเช่น Clang หรือ DMS จากสด คุณไม่สามารถที่จะโยนแอปพลิเคชันที่คุณเขียนไว้กับทีม 10 กว่า 5 ปี เราจะต้องใช้เครื่องมือดังกล่าวบ่อยขึ้นเรื่อย ๆ เนื่องจากขนาดของซอฟต์แวร์และอายุการใช้งานยังคงเพิ่มขึ้นอย่างต่อเนื่อง
Ira Baxter

@StevenLu: อืม DMS ขอบคุณสำหรับคำชม แต่ไม่มีอะไรวิเศษเกี่ยวกับมัน DMS ได้รับประโยชน์จากเกือบสองทศวรรษที่ผ่านมาในเชิงเส้นของวิศวกรรมและแพลตฟอร์มสถาปัตยกรรมที่สะอาด (aw, shucks, YMMV) ที่จัดขึ้นค่อนข้างดี ในทำนองเดียวกันเสียงดังกราวมีวิศวกรรมที่ดีมากมาย ฉันเห็นด้วยพวกเขาไม่ได้ถูกออกแบบมาเพื่อแก้ปัญหาเดียวกัน ... ขอบเขตของ DMS มีจุดประสงค์ที่ชัดเจนมากขึ้นเมื่อพูดถึงการจัดการโปรแกรมเชิงสัญลักษณ์และมีขนาดเล็กลงเมื่อเป็นคอมไพเลอร์การผลิต
Ira Baxter

4

Metaprogramming ใน C ++ พร้อมด้วย API ของคอมไพเลอร์ (แทนที่จะใช้เทมเพลต) น่าสนใจและเป็นไปได้จริง เนื่องจาก metaprogramming นั้นยังไม่ได้มาตรฐานคุณจะต้องเชื่อมโยงกับคอมไพเลอร์เฉพาะซึ่งไม่ใช่กรณีที่มีเทมเพลต

ดังนั้นฉันสงสัยว่าทำไมทุกคนไม่ได้ทำเช่นนี้ ฟังก์ชั่นนี้จาก clang นั้นใหม่และไม่มีใครคุ้นเคยกับ AST ของ clang ในระดับชั้นเรียนขนาดใหญ่? ไม่สามารถทำได้

หลายคนทำเช่นนี้ แต่ในภาษาอื่น ๆ ความคิดเห็นของฉันคือนักพัฒนา C ++ (หรือ Java หรือ C) ส่วนใหญ่ไม่เห็นความต้องการ (อาจถูกต้อง) หรือไม่สอดคล้องกับแนวทางการใช้โปรแกรม ฉันยังคิดว่าพวกเขามีความสุขกับคุณสมบัติการสร้าง / สร้างรหัสของ IDE ของพวกเขาและสิ่งที่นักเล่นอาจจะเห็นว่าซับซ้อนเกินไป / ยากที่จะรักษา / ยากที่จะแก้ไขปัญหา หากไม่มีเครื่องมือที่เหมาะสมอาจเป็นเรื่องจริง คุณควรคำนึงถึงความเฉื่อยและปัญหาอื่น ๆ ที่ไม่ใช่ด้านเทคนิคเช่นการจ้างงานและ / หรือการฝึกอบรมผู้คน

อย่างไรก็ตามเนื่องจากเรากำลังพูดถึง Common LISP และระบบมาโคร (ดูคำตอบของ Basile) ฉันต้องบอกว่าเมื่อวานนี้Claspได้เปิดตัว (ฉันไม่ใช่ บริษัท ในเครือ):

Claspมุ่งมั่นที่จะใช้งาน Common LISP ที่สอดคล้องกับ LLVM IR ยิ่งไปกว่านั้นมันยังเปิดเผยไลบรารี Clang (AST, Matcher) ให้กับนักพัฒนา

  • ก่อนอื่นนั่นหมายความว่าคุณสามารถเขียนใน CL และไม่ต้องใช้ C ++ อีกต่อไปยกเว้นเมื่อใช้ไลบรารี (และถ้าคุณต้องการแมโครให้ใช้แมโคร CL)

  • ประการที่สองคุณสามารถเขียนเครื่องมือใน CL สำหรับรหัส C ++ ที่มีอยู่ (การวิเคราะห์การเปลี่ยนโครงสร้าง, ... )


3

คอมไพเลอร์ C ++ หลายตัวมี API ที่เสถียรและมีเอกสารมากหรือน้อยโดยเฉพาะอย่างยิ่งคอมไพเลอร์ซอฟต์แวร์ฟรีส่วนใหญ่

Clang / LLVMส่วนใหญ่เป็นห้องสมุดขนาดใหญ่และคุณสามารถใช้มันได้

ล่าสุดGCCเป็นยอมรับปลั๊กอิน โดยเฉพาะอย่างยิ่งคุณสามารถขยายได้โดยใช้MELT (ซึ่งเป็นตัว meta-plugin ซึ่งให้ภาษาเฉพาะโดเมนระดับสูงเพื่อขยาย GCC)

โปรดสังเกตว่าไวยากรณ์ของ C ++ นั้นไม่สามารถขยายได้อย่างง่ายดายใน GCC (และอาจไม่ใช่ใน Clang) แต่คุณสามารถเพิ่ม pragmas, builtins, attribute และ compiler pass ของคุณเองเพื่อทำสิ่งที่คุณต้องการ (อาจให้ macros preprocessor บางตัวเรียกสิ่งเหล่านี้ เพื่อให้ไวยากรณ์ที่ใช้งานง่าย)

คุณอาจสนใจในหลายภาษาและคอมไพเลอร์ดูเช่นการนำภาษาหลายขั้นตอนไปใช้โดยใช้ ASTs Gensym และกระดาษสะท้อนแสงโดย C.Calcagno et al และหลีกเลี่ยงMetaOcaml แน่นอนคุณควรดูในสิ่งอำนวยความสะดวกของแมโครCommon เสียงกระเพื่อม และคุณอาจสนใจห้องสมุด JITเช่นlibjit , GNU lightning , แม้แต่LLVM , หรือเพียงแค่ -at run-time! - สร้างรหัส C ++ บางส่วน, รวบรวมการรวบรวมไว้ในไลบรารีวัตถุแบบไดนามิกที่ใช้ร่วมกัน, จากนั้นdlopen (3)ที่ใช้ร่วมกัน วัตถุ. บล็อกของ J.Pitratยังเกี่ยวข้องกับวิธีการไตร่ตรองดังกล่าว และยังRefPerSys


น่าสนใจ นั่นเป็นเรื่องดีมากที่จะเห็น GCC พัฒนาต่อไปที่นี่ นี่ไม่ใช่คำตอบที่ตอบสิ่งที่ฉันถาม แต่ฉันชอบมัน
Steven Lu

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