การเรนเดอร์th-TH

Glyphs and Latin

Glyphs and operators#

Faber ใช้สัญลักษณ์ที่มีบทบาทเชิงโครงสร้าง ด้านล่างคือรายการสัญลักษณ์ต้นฉบับทั้งหมดที่ lexer รองรับ

การไหลของค่า#

สัญลักษณ์ความหมาย
การผูกค่า การกำหนดค่าใหม่ และการกลายค่า ณ ขณะทำงาน
ชนิดค่าที่ฟังก์ชันส่งคืน
ทางออกสำรอง — ชนิดของช่องทางข้อผิดพลาด หรือการกู้คืนจากการแปลงค่าแบบอินไลน์
ตัวเชื่อมปิดล้อม — เชื่อมบอดีของปิดล้อมเข้ากับซิกเนเจอร์ ((a, b) → T ∴ a + b)

รูปร่างของชนิด#

สัญลักษณ์ความหมาย
การระบุชนิดแบบคงที่ (การแคสต์ระหว่างคอมไพล์)
การแปลงค่าระหว่างทำงาน (การแยกวิเคราะห์หรือบังคับชนิดที่อาจล้มเหลว)
ชนิดยูเนียนแบบอินไลน์ (T ∪ nihil)

การเปรียบเทียบ#

สัญลักษณ์ความหมาย
ความเท่ากันและไม่เท่ากันแบบตรงทั้งหมด
< > การเรียงลำดับ
ความเท่ากันของค่าตัวเลข

ตรรกะและบิต#

สัญลักษณ์ความหมาย
¬และ หรือ xor ไม่
การเลื่อนบิตไปทางซ้ายและขวา

การปรับค่าด้วยการกำหนดค่า#

สัญลักษณ์ความหมาย
ตัวดำเนินการกำหนดค่าเพียงตัวเดียวในนิพจน์
คำสั่งเพิ่มหรือลดค่าแบบ postfix (ใช้ได้กับ numerus ที่เปลี่ยนค่าได้เท่านั้น)

การเชื่อมต่อแบบเลือกได้และการยืนยันว่าไม่เป็นค่าว่าง#

สัญลักษณ์ความหมาย
? ?. ?[ ?(การเชื่อมต่อแบบเลือกได้
! !. ![ !(การยืนยันว่าไม่เป็นค่าว่าง

ช่วงค่า#

สัญลักษณ์ความหมาย
จุดสิ้นสุดของช่วงแบบไม่รวมปลาย
จุดสิ้นสุดของช่วงแบบรวมปลาย

ตัวคั่นลิเทอรัล#

สัญลักษณ์ชนิดบทบาท
'asciiโทเคนคงที่สำหรับเครื่อง
"textusสตริงบรรทัดเดียว
« »textusสตริงหลายบรรทัดแบบบล็อก (เครื่องหมายกีเยอเมต์)
`formaเทมเพลตที่บันทึกค่า
``octetiลิเทอรัลเลขฐานสิบหก
§ช่องว่างของเทมเพลตตัวยึดภายใน "…", «…»,

เครื่องหมายวรรคตอน#

สัญลักษณ์บทบาท
( )การจัดกลุ่มและการเรียกใช้
{ }บล็อก ลิเทอรัล genus หรือเอกสาร JSON
[ ]ลิเทอรัลลิสต์และการทำดัชนี
.การเข้าถึงสมาชิก
,ตัวคั่น
;ตัวคั่นคำสั่ง
:ตัวคั่นฟิลด์ JSON
=รูปร่างฟิลด์เชิงโครงสร้าง (ไม่ใช่การกำหนดค่าระหว่างทำงาน)
@เครื่องหมายแอนโนเทชัน
#ความคิดเห็นท้ายบรรทัด

Latin vocabulary and structural glyphs#

สัญญาณสามประการที่ทำให้ซอร์ส Faber สังเกตได้ทันที

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

สัญญาณสามประการ#

สัญญาณตัวอย่างบทบาท
การประกาศแบบชนิดข้อมูลนำหน้าtextus nomen, numerus aetasรูปแบบมุ่งไปสู่การผูกค่า — ชนิดข้อมูลก่อน แล้วจึงตามด้วยชื่อ
คำพฤติกรรมภาษาละตินfunctio, genus, si, redde, fixumการประกาศ คำสั่ง วงจรชีวิต และเจตนาเชิงพฤติกรรม
อักขระโครงสร้าง← → ∴ ≡ ∪ ⇥การไหลของค่า การไหลของชนิดข้อมูล และจุดเชื่อมเชิงโครงสร้าง — เป็นสากลและไม่เคยแปลเป็นภาษาท้องถิ่น

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

การประกาศแบบชนิดข้อมูลนำหน้า#

Faber วางชนิดข้อมูลไว้ก่อนชื่อในการประกาศทุกชนิด ซึ่งตรงข้ามกับไวยากรณ์ของภาษาในตระกูล C ที่ใช้กันทั่วไป และเป็นการออกแบบโดยเจตนา:

โครงสร้างรูปแบบที่คุ้นเคยในตระกูล CFaber
ตัวแปรint count = 0numerus count ← 0
ฟังก์ชันfn greet(name: String) → Stringfunctio salve(textus nomen) → textus
พารามิเตอร์(String name)(textus nomen)

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

ฟังก์ชัน divide(จำนวน a, จำนวน b)  จำนวน  ว่าง {
    ถ้า b  0 ดังนั้น คืน ว่าง
    คืน a / b
}

คำศัพท์พฤติกรรมภาษาละติน#

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

การประกาศ#

คีย์เวิร์ดบทบาทคำเทียบเคียงโดยประมาณ
functioประกาศฟังก์ชันหรือเมธอดที่มีชื่อfn, def, function
genusประกาศชนิดข้อมูลรูปธรรมที่มีฟิลด์class, struct
implendumประกาศสัญญาเชิงพฤติกรรมinterface, trait
typusประกาศนามแฝงของชนิดข้อมูลtypedef, type
discretioประกาศยูเนียนแบบมีแท็กenum, sum type

การผูกค่าและการส่งผ่าน#

คีย์เวิร์ดบทบาทคำเทียบเคียงโดยประมาณ
fixumการผูกค่าที่ไม่เปลี่ยนแปลง (เขียนได้ครั้งเดียว)let, const
variaการผูกค่าที่เปลี่ยนแปลงได้let mut, var
sitการผูกค่าคงที่แบบอนุมานชนิดข้อมูลอย่างกระชับlet (อนุมานชนิดข้อมูล)
reddeคืนค่าจากฟังก์ชันreturn
iaceโยนข้อผิดพลาดผ่านช่องทางข้อผิดพลาดthrow, raise
moriเลื่อนการทำงาน — ยังไม่สามารถแสดงพฤติกรรมนี้ได้unimplemented!, todo

การไหลควบคุม#

คีย์เวิร์ดบทบาทคำเทียบเคียงโดยประมาณ
siแขนงเงื่อนไขif
sinแขนงอื่นเมื่อเงื่อนไขก่อนหน้าไม่เป็นจริงelse if
secusแขนงอื่นelse
dumลูปขณะเงื่อนไขเป็นจริงwhile
iteraการวนซ้ำ (ค่า คีย์ หรือช่วง)for
eligeจับคู่รูปแบบ (เลือกแขนงแรกที่ตรงกัน)match, switch
facบล็อกทดลองทำงานพร้อมกู้คืนจากข้อผิดพลาดtry, do
capeตัวจัดการข้อผิดพลาดสำหรับ faccatch

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

อักขระโครงสร้าง#

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

การไหลของค่า#

อักขระความหมาย
การผูกค่าระหว่างรันไทม์ การกำหนดค่าใหม่ และการเปลี่ยนแปลงค่า — เป็นตัวดำเนินการกำหนดค่าเพียงตัวเดียว
การประกาศชนิดข้อมูลผลลัพธ์ของฟังก์ชัน
ทางออกสำรอง: ชนิดข้อมูลของช่องทางข้อผิดพลาด หรือการกู้คืนจากการแปลงค่าแบบอินไลน์
ตัวเชื่อมปิดล้อม — เชื่อมบอดีของปิดล้อมเข้ากับซิกเนเจอร์

รูปร่างของชนิดข้อมูล#

อักขระความหมาย
การระบุชนิดข้อมูลแบบสแตติก — การยืนยันชนิดข้อมูลของค่าในเวลาคอมไพล์
การแปลงค่าระหว่างรันไทม์ — การแยกวิเคราะห์หรือการบังคับชนิดข้อมูลที่อาจล้มเหลว
ชนิดข้อมูลยูเนียนแบบอินไลน์ — เชื่อมชนิดข้อมูลสองชนิดเข้าด้วยกัน (เช่น T ∪ nihil)

การเปรียบเทียบและตรรกะ#

อักขระความหมาย
ความเท่ากันและไม่เท่ากันอย่างแม่นยำ — ต้องตรงชนิดข้อมูลอย่างเคร่งครัด
< > การเปรียบเทียบลำดับ
¬ตรรกะและการดำเนินการระดับบิต: และ หรือ xor ไม่

หลักการผูกค่ามีความสำคัญ#

การเลือกใช้อักขระหนึ่งควรได้รับความสนใจเป็นพิเศษ เพราะเป็นจุดที่ผู้อ่านใหม่มักสับสนมากที่สุด:

อักขระบทบาทใช้สำหรับ
การไหลระหว่างรันไทม์การผูกค่าเริ่มต้น การกำหนดค่าใหม่ และการเปลี่ยนแปลงค่าระหว่างการทำงาน
=รูปร่างเชิงโครงสร้างชื่อฟิลด์ภายในลิเทอรัลและเมทาดาทาของการประกาศ — ไม่ใช่การจัดเก็บค่าระหว่างรันไทม์

ภาษาส่วนใหญ่ใช้ = ซ้ำสำหรับทั้ง “กำหนดฟิลด์นี้ในชนิดข้อมูล” และ “ใส่ค่าระหว่างรันไทม์ลงในตัวแปรนี้” Faber แยกหน้าที่ทั้งสองออกจากกัน ทุก คือการไหลของข้อมูลที่ทำงานจริง ทุก = ภายใน Type { … } คือโครงร่างฟิลด์ของ genus

# Runtime binding: ← attaches a value to a name
fixum numerus count ← 0
varia textus label ← "ready"
count ← count + 1

# Structural shape: = defines field values inside a literal
fixum _ p ← Point {
    x = 10,
    y = 20
}

เมื่อเปรียบเทียบกับภาษาที่ใช้กันทั่วไป#

ตารางต่อไปนี้แสดงว่ารูปแบบการเขียนโปรแกรมที่พบบ่อยม映ไปยังระบบสัญญาณสามประการของ Faber อย่างไร คอลัมน์ Faber ใช้อักขระหรือคีย์เวิร์ดที่แตกต่างกันสำหรับงานเชิงความหมายแต่ละประเภท — ไม่มีการใช้ซ้ำหลายความหมาย

งานเชิงความหมายภาษาทั่วไปFaber
การประกาศชนิดข้อมูลของพารามิเตอร์name: Stringtextus nomen
ชนิดข้อมูลผลลัพธ์→ String, : String textus
การกำหนดค่าระหว่างรันไทม์x = value
การทดสอบความเท่ากัน==
ค่าที่อาจว่างT?, Option<T>T ∪ nihil
แขนงที่มีคำสั่งเดียวif (cond) return xsi cond ergo redde x
การแปลงชนิดข้อมูล(T)value, value as Tvalue ∷ T
การแปลงค่า (อาจล้มเหลว)try_into()value ↦ T

แหล่งอ้างอิง#

  1. ไวยากรณ์ EBNF — รายการอักขระและคีย์เวิร์ดทั้งหมด
  2. examples/corpus/ — คลังภาษาที่มีไฟล์ตัวอย่าง 292 ไฟล์ ครอบคลุมคีย์เวิร์ดทั้งหมด
  3. examples/corpus/operatores/ — ตัวอย่างตัวดำเนินการและอักขระ
  4. บัญญัติ — กฎการออกแบบเก้าประการที่รักษาสัญญาณเหล่านี้

Canonical vs sugar surfaces#

หลายรูปแบบที่แยกวิเคราะห์ได้ แต่มีรูปแบบเชิงความหมายเดียวกัน

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

กฎ: รูปแบบย่อมีความหมายเหมือนกับรูปแบบเต็มทุกประการ รูปแบบการเขียนหลายแบบถูกแยกวิเคราะห์เป็น HirAnnotation หรือโหนดชนิดข้อมูลเดียวกัน faber format --canonical จะเลือกรูปแบบมาตรฐาน ส่วนโหมดผู้เขียนจะคงรูปแบบย่อที่ผู้เขียนระบุไว้

รูปแบบย่อของชนิดข้อมูลตัวเลข#

ชนิดข้อมูลตัวเลขมีรูปแบบการเขียนเต็มที่เป็นมาตรฐาน และมีรูปแบบย่อที่กระชับกว่า การเลือกใช้เป็นเรื่องระดับโมดูล ไม่ใช่ระดับรีโพซิทอรี — แพ็กเกจ CLI อาจใช้รูปแบบเต็มทั้งหมด ขณะที่โมดูลเคอร์เนลเทนเซอร์อาจใช้รูปแบบย่อ:

รูปแบบย่อรูปแบบมาตรฐานขอบเขตการใช้งาน
f32, f64, i32, u64fractus<f32>, numerus<i32>ตัวระบุความกว้าง — ชนิดข้อมูลตัวเลขสเกลาร์
tf32, tf32[4], ti64[2, 3]tensor<f32, _>, tensor<f32, [4]>เทนเซอร์หนาแน่น — t + ความกว้าง + รูปร่างที่เป็นตัวเลือก
sf32, sf32[2, 3], si64[N]sparsa<f32, _>, sparsa<f32, [2, 3]>เทนเซอร์กระจาย — s + ความกว้าง + รูปร่างที่เป็นตัวเลือก
mf32[4, 4], mu32[3, 3]matrix<f32, [4, 4]>เมทริกซ์คลาสรีจิสเตอร์ — m + ความกว้าง + รูปร่าง
lf32, lu32, li64lista<f32>, lista<u32>รายการ — l + ความกว้าง
f16fractus<f16>ตัวระบุความกว้างของ half-float (มีผลต่อความหมายและเลย์เอาต์เท่านั้น)

Faber ทั่วไป (แนะนำให้ใช้รูปแบบเต็ม):

คงที่ รายการ<f32> values  เซตว่าง

คงที่ เทนเซอร์<f32, [2, 3]> grid  เซตว่าง

คงที่ จำนวน<i32> narrow  7

โมดูลตัวเลข (แนะนำให้ใช้รูปแบบย่อ):

คงที่ รายการ<f32> values  เซตว่าง

คงที่ เทนเซอร์<f32, [2, 3]> grid  เซตว่าง

คงที่ จำนวน<i32> narrow  7

รูปแบบย่อใช้ได้ เฉพาะในตำแหน่งชนิดข้อมูลเท่านั้น ตัวระบุค่าที่ชื่อ f32, tf32 หรือ mf32 จะไม่เปลี่ยนแปลง — คอมไพเลอร์จะตีความสิ่งเหล่านี้เป็นรูปแบบย่อก็ต่อเมื่อปรากฏในตำแหน่งชนิดข้อมูลเท่านั้น ไฟล์ที่ใช้รูปแบบย่ออย่างสม่ำเสมอควรประกาศเรื่องนี้ไว้หนึ่งครั้งที่ด้านบน:

# STYLE: numeric sugar (tf32, mf32, sf32, lf32, lu32)

รูปแบบย่อของแอนโนเทชัน#

แอนโนเทชันของ Faber ใช้โมเดลสองรูปแบบเดียวกับชนิดข้อมูลตัวเลข แอนโนเทชันคือข้อมูลเมทาดาทาที่คอมไพเลอร์เป็นเจ้าของและแนบไว้กับการประกาศ — เช่น @ optio สำหรับนิยามตัวเลือก CLI หรือ @ futura สำหรับฟังก์ชันอะซิงก์

รูปแบบมาตรฐาน: เรกคอร์ดในวงเล็บปีกกาที่ระบุชื่อฟิลด์อย่างชัดเจน:

@ optio {
    binding = verbose,
    brevis = "v",
    longum = "verbose",
    typus = bivalens,
    ubique = verum,
    descriptio = "Enable verbose output"
}

รูปแบบย่อ: อาร์กิวเมนต์ตามลำดับและชื่อแทน:

@ optio verbose brevis "v" longum "verbose" typus bivalens ubique descriptio "Enable verbose output"

ทั้งสองรูปแบบสร้างเรกคอร์ด HirAnnotation เดียวกัน รูปแบบมาตรฐานมีความชัดเจนและอธิบายตัวเองได้ ส่วนรูปแบบย่อเหมาะกับแอนโนเทชันที่ใช้บ่อยและมีลำดับฟิลด์ที่ผู้ใช้ทราบกันดี faber format --canonical จะเลือกเรกคอร์ดในวงเล็บปีกกา ส่วนโหมดผู้เขียนจะคงรูปแบบที่ผู้เขียนเลือกไว้

การจัดรูปแบบแบบผู้เขียนเทียบกับแบบมาตรฐาน#

คำสั่ง faber format ทำงานในสองโหมด ซึ่งสอดคล้องกับหลักการรูปแบบมาตรฐานเทียบกับรูปแบบย่อ:

โหมดคำสั่งอินพุตเอาต์พุต
ผู้เขียนfaber formatAST ที่แยกวิเคราะห์แล้ว + trivia ที่อยู่ด้านหน้าซอร์ส Faber ที่คงคอมเมนต์ #, บรรทัดว่าง และรูปแบบย่อ
มาตรฐานfaber format --canonicalHIR ที่ผ่านการวิเคราะห์แล้ว + TypeTableFaber ที่ทำให้เป็นมาตรฐาน — ไม่มีคอมเมนต์ ใช้รูปแบบมาตรฐาน และไม่มีรูปแบบย่อ

ทั้งสองโหมดทำงานผ่านส่วนหน้าทั้งหมดของคอมไพเลอร์ (lex, parse, analyse สำหรับโหมดมาตรฐาน) ซอร์สที่ไม่ถูกต้องจะสร้างไดแอกโนสติกจากคอมไพเลอร์ — ฟอร์แมตเตอร์จะไม่จัดรูปแบบอินพุตที่เสียโดยไม่แจ้งให้ทราบ

กฎสำคัญสำหรับทั้งสองโหมด:

  • การเยื้องสี่ช่องว่าง
  • วงเล็บปีกกาแบบ Stroustrup: { เปิดในบรรทัดเดียวกับส่วนหัวควบคุม
  • โหมดผู้เขียนจะคง การมีอยู่ ของบรรทัดว่างไว้ แต่จะรวมบรรทัดว่างที่ต่อเนื่องกันมากกว่าหนึ่งบรรทัด
  • โหมดผู้เขียนจะไม่แทรกบรรทัดว่างที่ไม่มีอยู่ในซอร์สเดิม
  • โหมดมาตรฐานจะปรับรูปแบบการเขียนชนิดข้อมูลให้เป็นรูปแบบเต็ม ปรับรูปแบบย่อของเทนเซอร์ให้เป็นรูปแบบมาตรฐาน และปรับแอนโนเทชันให้เป็นเรกคอร์ดในวงเล็บปีกกา
  • โหมดมาตรฐานจะส่งออก T ∪ nihil สำหรับยูเนียนที่รองรับค่า null และ sponte สำหรับพารามิเตอร์ที่เป็นตัวเลือก

หลักการออกแบบ#

รูปแบบมาตรฐานเทียบกับรูปแบบย่อปรากฏในหลายส่วน เพราะนี่คือหลักการออกแบบโดยเจตนา ไม่ใช่ชุดความสะดวกแบบเฉพาะจุด:

ขอบเขตมาตรฐานรูปแบบย่อ
ชนิดข้อมูลตัวเลขnumerus<i32>i32
ชนิดข้อมูลเทนเซอร์tensor<f32, [4]>tf32[4]
แอนโนเทชัน@ optio { binding = verbose }@ optio verbose ...
การจัดรูปแบบfaber format --canonicalfaber format (โหมดผู้เขียน)
โลแคลสำหรับผู้อ่านละติน (la)แพ็กโลแคลใดก็ได้

รูปแบบนี้มีเป้าหมายสองประการ ประการแรก ลดอุปสรรคในการเริ่มต้นใช้งาน — ผู้ใช้ใหม่สามารถเขียน tf32[4] ได้โดยไม่ต้องพิมพ์ tensor<fractus<f32>, [4]> ประการที่สอง รักษาความไม่กำกวมของภาษามาตรฐาน — เมื่อความแม่นยำเป็นสิ่งสำคัญ รูปแบบเต็มจะระบุความหมายไว้อย่างชัดเจน ฟอร์แมตเตอร์ทำหน้าที่เชื่อมระหว่างสองรูปแบบนี้: ผู้เขียนเขียนรูปแบบย่อ ผู้ตรวจสอบสามารถขอรูปแบบมาตรฐาน และ CI สามารถบังคับใช้รูปแบบใดรูปแบบหนึ่งได้

เอกสารอ้างอิง#

  1. radix/docs/design/numeric-type-sugar.md — ตระกูลรูปแบบย่อทั้งหมดและแนวทางเลือกรูปแบบการเขียน
  2. radix/docs/design/annotation-sugar.md — โมเดลแอนโนเทชันสองรูปแบบ
  3. radix/docs/design/faber-canonical-surface.md — นโยบายรูปแบบผู้เขียนเทียบกับรูปแบบมาตรฐาน
  4. faber/docs/EBNF.md — ตารางไวยากรณ์สำหรับรูปแบบย่อ