Design notes
Commandments#
กฎเก้าข้อที่ทำให้ Faber ให้ความรู้สึกเป็น Faber
กฎเหล่านี้คือหลักการออกแบบที่กำหนดลักษณะเฉพาะของ Faber ไวยากรณ์อาจพัฒนาได้ และสามารถเพิ่มฟีเจอร์ใหม่ได้ แต่การเปลี่ยนแปลงควรรักษาหลักการเหล่านี้ไว้ โปรแกรมที่ละเมิดหลักการเหล่านี้อาจยังเป็น Faber ที่ถูกต้อง แต่จะไม่ให้ความรู้สึก เป็น Faber
บัญญัติเหล่านี้ใช้ได้กับทุกระดับ — ตั้งแต่ตัวไวยากรณ์เองไปจนถึงวิธีตั้งชื่อ API ในไลบรารีมาตรฐาน นี่คือเหตุผลที่ผู้อ่านสามารถระบุซอร์สโค้ด Faber ได้ทันที ไม่ว่าจะเรนเดอร์คีย์เวิร์ดด้วยภาษามนุษย์ใด หรือโค้ดจะคอมไพล์ไปยังแบ็กเอนด์เป้าหมายใด
I. ประเภทมาก่อนชื่อ#
การประกาศอ่านจากรูปร่างไปสู่การผูกชื่อ ประเภทมาก่อนเพราะผู้อ่านจำเป็นต้องรู้ สิ่งนี้เป็นสิ่งประเภทใด ก่อนที่ชื่อจะบอกว่า เป็นสิ่งใด ลำดับนี้สอดคล้องกับ ภาษาที่มีโครงสร้างทางไวยากรณ์จากหมวดหมู่ไปยังสิ่งเฉพาะ — เช่น ภาษาจีน ภาษาฮินดี และภาษาอาหรับ — และทำให้การประกาศกวาดสายตาได้อย่างสม่ำเสมอ
# Type before name in every declaration
textus nomen
numerus aetas
functio salve(textus name) → textusII. ใช้กลไกที่ชัดเจน ไม่พึ่งเวทมนตร์#
โครงสร้างเดียวกันควรมีความหมายเหมือนกันในทุกที่ หากผู้อ่านต้องอาศัยบริบทที่อยู่ ห่างไกลเพื่อรู้ว่าสัญลักษณ์หนึ่งทำอะไร ไวยากรณ์นั้นก็น่าสงสัย Faber ให้ความสำคัญ กับการให้เหตุผลอย่างชัดเจนและอยู่ในบริเวณใกล้เคียง — จุดประกาศควรมีข้อมูลเพียงพอ ให้เข้าใจได้ว่าจะเกิดอะไรขึ้นที่จุดใช้งาน
# The meaning of a call is determined by the function's signature,
# not by invisible trait resolution or implicit conversions.
ฟังก์ชัน duplica(จำนวน n) → จำนวน {
คืน n * 2
}III. อักขระภาพทำหน้าที่บอกโครงสร้าง#
ความหมายเชิงโครงสร้างและตัวดำเนินการใช้สัญลักษณ์ภาพ ไม่ใช้คำ: ←
สำหรับการผูกค่า, → สำหรับประเภทผลลัพธ์, ⇥
สำหรับการออกเมื่อเกิดข้อผิดพลาด, ergo สำหรับบอดีของแขนงแบบกระชับ,
≡ สำหรับความเท่ากัน และ ∪ สำหรับประเภท
ยูเนียน สัญลักษณ์ภาพเป็นสากล — ไม่แปลตามภาษาและไม่เปลี่ยนความหมาย
ระหว่างการเรนเดอร์ ภาษาไทยและภาษาฝรั่งเศสจึงเห็นสัญลักษณ์ภาพเดียวกัน
แม้คีย์เวิร์ดที่อยู่รอบข้างจะแตกต่างกัน
IV. อักษรละตินทำหน้าที่บอกพฤติกรรม#
คำต่าง ๆ ใช้สำหรับการประกาศ คำสั่ง วงจรชีวิต และเจตนาเชิงพฤติกรรม:
ฟังก์ชัน, ชนิด, คงที่,
แปร, คืน, จับ
คำเหล่านี้สามารถผูกเข้ากับแพ็กภาษาของผู้อ่านได้ — คำเหล่านี้คือคลังคำศัพท์
ไม่ใช่ไวยากรณ์ การเลือกใช้ภาษาละตินไม่ได้หมายถึงความเหนือกว่าของภาษาละติน
แต่หมายถึงการเลือกแหล่งภาษาคลาสสิก เพียงแหล่งเดียว ที่สอดคล้องกัน
เพื่อให้คีย์เวิร์ดทั้งหมดอยู่ในระดับภาษาเดียวกัน และไม่มีคีย์เวิร์ดใดได้รับสิทธิพิเศษ
เพียงเพราะเป็นภาษาที่ใช้เขียนตัวระบบ
V. การผันคำกริยาทำหน้าที่บอกเวลาและการไหลของการทำงาน#
เมื่อสามารถเรียกใช้ตรรกะรากเดียวกันแบบซิงโครนัส แบบอะซิงโครนัส
หรือในฐานะเจเนอเรเตอร์ได้ รูปผันของคำกริยาควรเป็นตัวบอกโหมดการทำงานนั้น
คู่คำที่เกี่ยวกับ ownership — กลายค่าเทียบกับคัดลอกผลลัพธ์ออก —
ควรใช้รูปที่สัมพันธ์กันของรากคำเดียวกัน นี่คือหลักการ morphologia
ไลบรารีมาตรฐาน (Norma) ใช้แบบแผนนี้กับชื่อเมธอดทั้งหมด:
lege (อ่านแบบซิงโครนัส) เทียบกับ
leget (อ่านแบบอะซิงโครนัส), adde (กลายค่าในที่เดิม) เทียบกับ
addita (คืนสำเนาใหม่) คอมไพเลอร์ไม่ได้บังคับหรือสร้างรูปผันเหล่านี้
เพราะนี่เป็นนโยบายการตั้งชื่อ ไม่ใช่ฟีเจอร์ของภาษา
VI. หนึ่งสัญลักษณ์ หนึ่งหน้าที่#
สัญลักษณ์ภาพหรือคีย์เวิร์ดอาจมีนามแฝงที่มีความหมายตรงกันได้
แต่ไม่ควรมีความหมายที่ไม่เกี่ยวข้องกัน นามแฝงต้องชี้กลับไปยังแนวคิดหลักเพียงหนึ่งเดียว
นี่คือหลักการที่ขับเคลื่อนการแยกระหว่าง ←
(การผูกค่าในขณะทำงาน) และ = (รูปร่างฟิลด์เชิงโครงสร้าง) —
ภาษาส่วนใหญ่รวมทั้งสองอย่างไว้เป็น =
แต่การใช้ซ้ำเช่นนั้นบดบังว่าบรรทัดหนึ่งเป็นการดำเนินการไหลของข้อมูล
หรือเป็นการกำหนดในระดับประเภท
# ← is always runtime flow
fixum numerus count ← 0
count ← count + 1
# = is always structural shape inside Type { }
fixum _ p ← Point {
x = 10,
y = 20
}VII. การไหลของการทำงานขณะรันไทม์ต้องชัดเจน#
การผูกค่าในขณะทำงาน การกำหนดค่าใหม่ และการกลายค่าใช้ ←;
การกำหนดเชิงโครงสร้างใช้ = ผู้อ่านที่กวาดสายตาผ่านซอร์สโค้ดจะเห็น
การดำเนินการไหลของข้อมูลทุกจุดได้ทันที: ทุก ← คือเหตุการณ์ขณะรันไทม์
จึงไม่มีความกำกวมทางไวยากรณ์ว่า = ในบรรทัดหนึ่งหมายถึง
“เก็บค่าลงในตัวแปรนี้” หรือ “กำหนดฟิลด์นี้”
VIII. การไม่มีค่าต้องมีประเภท#
ประเภทค่าที่อาจเป็นค่าว่างเขียนเป็นยูเนียน: T ∪ nihil
ช่องการประกาศที่เลือกละเว้นได้ใช้เครื่องหมายหลังชื่อ: sponte
สองอย่างนี้เป็นแนวคิดที่แตกต่างกัน — ค่าที่อาจไม่มีอยู่ เทียบกับ
ช่องที่ผู้เรียกอาจไม่ระบุ — และ Faber แยกสองแนวคิดนี้ทางไวยากรณ์
แทนที่จะรวมทั้งคู่ไว้เป็น T? หรือ Option<T>
# Absence in a value: T ∪ nihil
functio find(textus key) → numerus ∪ nihil
# Omission at declaration: sponte
functio connect(textus host, numerus port sponte) → vacuumIX. คอมไพเลอร์จะไม่เดาเพื่อปกปิดข้อมูลที่ขาดหาย#
ข้อมูลประเภทที่ขาดหายเป็นปัญหาด้านการวิเคราะห์ที่ต้องแก้จากต้นทาง ไม่ใช่รายละเอียดของการสร้างโค้ดที่ควรปกปิด คอมไพเลอร์จะไม่อนุมานประเภท ที่โปรแกรมเมอร์ไม่ได้ระบุอย่างเงียบ ๆ เมื่อข้อมูลนั้นขาดหายไปจริง — คอมไพเลอร์จะแจ้งช่องว่างดังกล่าวแล้วหยุดทำงาน กฎนี้ทำให้ Faber ซื่อตรง: หากผู้อ่านไม่สามารถระบุความหมายของสัญลักษณ์จากซอร์สโค้ดบริเวณใกล้เคียงได้ คอมไพเลอร์ก็ไม่ควรแสร้งทำเป็นว่าระบุได้
จุดประสงค์#
บัญญัติเหล่านี้มีขึ้นเพื่อตอบคำถามที่เกิดขึ้นในการอภิปรายการออกแบบภาษา ทุกครั้งว่า “การเปลี่ยนแปลงนี้ยังเป็น Faber อยู่หรือไม่” บัญญัติเหล่านี้คือ เกณฑ์ตรวจสอบความคงเส้นคงวา — ไม่ใช่การตรวจเทียบกับรายการฟีเจอร์ แต่เป็นการตรวจเทียบกับลักษณะเฉพาะ การเปลี่ยนแปลงที่ละเมิดบัญญัติอาจยังเป็น แนวคิดที่ดี แต่ควรยอมรับอย่างชัดเจนว่าเป็นการออกนอกลักษณะการออกแบบของ Faber ไม่ใช่การเพิ่มฟีเจอร์ตามปกติ
ในทางปฏิบัติ บัญญัติเหล่านี้มักใช้เป็นเกณฑ์ทบทวนข้อเสนอไวยากรณ์ใหม่ ข้อเสนอที่ทำให้หลัก “ประเภทมาก่อนชื่อ” อ่อนลงด้วยการเพิ่มทางเลือกแบบชื่อมาก่อน หรือทำให้หลัก “หนึ่งสัญลักษณ์ หนึ่งหน้าที่” พร่ามัวด้วยการใช้สัญลักษณ์ภาพ หลายความหมาย ต้องอธิบายให้ได้ว่าเหตุใด Faber จึงควรยืดหยุ่นลักษณะเฉพาะของตน เพื่อรองรับฟีเจอร์นั้น
Design documents#
คลัง Radix มีเอกสารการออกแบบที่เป็นแหล่งอ้างอิงหลักเกี่ยวกับการทำงานของ Faber ในฐานะภาษาและคอมไพเลอร์ เอกสารเหล่านี้อยู่ภายใต้ radix/docs/design/
ดัชนี#
| ด้าน | ไฟล์ |
|---|---|
| เป้าหมายและการลดรูป | target-capability-matrix.md, lowering-routes.md, semantic-ownership.md |
| ชนิดข้อมูลและไวยากรณ์ย่อ | numeric-type-sugar.md, comparison-operators.md, annotation-sugar.md |
| อินทรินสิกของคอลเลกชัน | lista-intrinsics.md, tabula-intrinsics.md, tensor-intrinsics.md, numerus-intrinsics.md, fractus-intrinsics.md, textus-intrinsics.md, intervallum-intrinsics.md, instans-intrinsics.md, copia-intrinsics.md |
| การแปลงค่า | conversio-valor.md, failable-conversio.md |
| เฟรมและเอฟเฟกต์ | frame-stream-types.md, host-provider-gateway.md |
| รีดเดอร์และรูปแบบ | reader-locale.md, faber-canonical-surface.md |
| ระบบ / AIR | air-dialect.md, aiml-foundation.md, systems-shaped-values.md |
| พื้นผิวเครื่องมือ | faber-scripting.md |
| หนี้ค้างด้านการตั้งชื่อ | mixed-case-naming-debt.md |
เอกสารการออกแบบไลบรารีมาตรฐาน#
ไดเรกทอรี radix/docs/stdlib/ ประกอบด้วย:
| เอกสาร | บทบาท |
|---|---|
morphologia.md | นโยบายการผันรูปสำหรับชื่อเมธอดทั้งหมดในไลบรารีมาตรฐาน |
tensor-methods.md | เอกสารอ้างอิงเมธอดของตัวรับ Tensor |
chorda-methods.md | เอกสารอ้างอิงเมธอดของ Chorda (ข้อความ) |
mathesis-methods.md | เอกสารอ้างอิงเมธอดทางคณิตศาสตร์ |
tempus-methods.md | เอกสารอ้างอิงเมธอดด้านเวลา |
stdlib-mechanical-verbs.md | นโยบายสามคำกริยา pange/solve/tempta |
History#
จุดกำเนิด#
คอมมิตแรกของคอมไพเลอร์ Radix เกิดขึ้นเมื่อ 20 ธันวาคม 2025
ในรูปแบบโปรเจกต์ Bun + TypeScript ที่มีไฟล์ docs/decisions.md เพียงไฟล์เดียว
คอมมิตที่สองได้กำหนดบันทึกการตัดสินใจด้านสถาปัตยกรรม (Architecture Decision Records)
ไว้ห้ารายการ ซึ่งยังคงกำหนดทิศทางของภาษาในปัจจุบัน
ADR-003 ซึ่งมีชื่อว่า "การลงท้ายของคำบ่งบอกความหมายเชิงอรรถศาสตร์" ได้วางหลักไว้ตั้งแต่เริ่มต้นว่า สัณฐานวิทยาของภาษาละตินจะมีบทบาทมากกว่า การเป็นเพียงผิวหน้าของคีย์เวิร์ด — คอมไพเลอร์จะเข้าใจการผันคำนามและการผันกริยา เพื่ออนุมานเจตนาของโปรแกรม การจับคู่รูปแบบกรณีดั้งเดิมมีดังนี้:
Nominative (subject) → return value, caller
Accusative (direct object) → primary argument
Dative (indirect obj.) → recipient, callback, destination
Genitive (possession) → property access, "of" relationships
Ablative (instrument) → dependencies, context, "using X"เอกสารฉบับเดียวกันยังระบุว่า: *"คำถามถัดไปตามธรรมชาติคือการผันกริยา
(อนาคตกาล → async?)"* เมล็ดพันธุ์นี้เติบโตเป็นหลักการตั้งชื่อ
morphologia ในปัจจุบัน โดยไลบรารีมาตรฐานใช้รูปกริยาภาษาละตินที่ผันแล้ว
เพื่อสื่อว่าเป็นการทำงานแบบ sync หรือ async และเป็นการกลายค่าเดิมหรือ
การคัดลอกผลลัพธ์ออกมา — โดยไม่กำหนดให้คอมไพเลอร์ต้องเข้าใจไวยากรณ์ภาษาละตินเอง
โครงการเริ่มต้นด้วย TypeScript จากนั้นจึงเขียนใหม่ด้วย Rust และตรึงไวยากรณ์ไว้
สำหรับสายรุ่น 1.x โดยใช้เอดิชัน 2026 ADR ดั้งเดิมทั้งห้ารายการ
(นามสกุลไฟล์ .fab, คำแนะนำข้อผิดพลาด, การลงท้ายของคำตามกรณี,
ตัวแยกวิเคราะห์แบบ recursive descent และ AST แบบกำหนดเอง)
ยังคงมองเห็นได้ในประวัติ git
รุ่นเผยแพร่#
ไฟล์ CLI ที่สร้างไว้ล่วงหน้า — รุ่น Faber ปัจจุบันอยู่ด้านบน ตามด้วยแท็กและไบนารีที่เผยแพร่แล้วทั้งหมดจาก faberlang/releases:
- [รุ่นเผยแพร่](/releases/) — ลิงก์ดาวน์โหลดและรายการประวัติ
- [ติดตั้งและดาวน์โหลด](/start/install.html) — การตั้งค่า PATH และการรัน
faber checkครั้งแรก