Kết xuấtvi

Glyphs and Latin

Glyphs and operators#

Faber sử dụng các glyph, trong đó ký hiệu mang vai trò cấu trúc. Dưới đây là toàn bộ danh mục glyph nguồn được lexer nhận diện.

Luồng giá trị#

GlyphÝ nghĩa
Liên kết, gán lại và biến đổi tại thời điểm chạy
Kiểu trả về của hàm
Lối thoát thay thế — kiểu kênh lỗi hoặc phục hồi chuyển đổi nội dòng
Khớp nối đóng — nối thân hàm đóng với chữ ký ((a, b) → T ∴ a + b)

Hình dạng kiểu#

GlyphÝ nghĩa
Gán kiểu tĩnh (ép kiểu tại thời điểm biên dịch)
Chuyển đổi tại thời điểm chạy (phân tích hoặc ép kiểu có thể thất bại)
Kiểu hợp nội dòng (T ∪ nihil)

So sánh#

GlyphÝ nghĩa
Bằng và khác chính xác
< > Thứ tự
Bằng nhau về giá trị số

Logic và thao tác bit#

GlyphÝ nghĩa
¬Và, hoặc, xor, phủ định
Dịch bit sang trái và sang phải

Cập nhật phép gán#

GlyphÝ nghĩa
Toán tử gán duy nhất trong biểu thức
Câu lệnh tăng hoặc giảm hậu tố (chỉ áp dụng cho numerus có thể biến đổi)

Chuỗi tùy chọn và khẳng định khác nihil#

GlyphÝ nghĩa
? ?. ?[ ?(Chuỗi tùy chọn
! !. ![ !(Khẳng định giá trị không phải nihil

Khoảng#

GlyphÝ nghĩa
Điểm cuối khoảng không bao gồm
Điểm cuối khoảng có bao gồm

Dấu phân cách literal#

GlyphKiểuVai trò
'asciiToken máy cố định
"textusChuỗi một dòng
« »textusChuỗi khối (dấu ngoặc kép kiểu guillemet)
`formaMẫu đã bắt giữ
``octetiLiteral thập lục phân
§lỗ mẫuPhần giữ chỗ bên trong "…", «…»

Dấu câu#

GlyphVai trò
( )Nhóm và lời gọi
{ }Khối, literal genus hoặc tài liệu JSON
[ ]Literal danh sách và phép lập chỉ mục
.Truy cập thành viên
,Dấu phân cách
;Dấu phân cách câu lệnh
:Dấu phân cách trường JSON
=Hình dạng trường cấu trúc (không phải phép gán tại thời điểm chạy)
@Dấu chú thích
#Chú thích dòng

Latin vocabulary and structural glyphs#

Ba lựa chọn tín hiệu giúp nhận ra mã nguồn Faber ngay từ cái nhìn đầu tiên.

Faber đưa ra ba lựa chọn tín hiệu có chủ đích. Chúng phối hợp để tạo ra mã nguồn có hình thái ngữ pháp ổn định. Người đọc có thể nhận ra vai trò ngữ nghĩa của từng cấu trúc trước khi biết mã nguồn sẽ được biên dịch sang backend đích nào.

Ba tín hiệu#

Tín hiệuVí dụVai trò
Khai báo đặt kiểu trướctextus nomen, numerus aetasHình dạng hướng về phép liên kết — kiểu, rồi đến tên.
Từ chỉ hành vi bằng tiếng Latinfunctio, genus, si, redde, fixumKhai báo, câu lệnh, vòng đời và chủ đích hành vi.
Ký hiệu cấu trúc← → ∴ ≡ ∪ ⇥Luồng giá trị, luồng kiểu và các mối nối cấu trúc — mang tính phổ quát, không bao giờ bản địa hoá.

Ba tín hiệu này được thiết kế để củng cố lẫn nhau. Người đọc biết Faber ở một bản địa hoá có thể đọc nó ở bất kỳ bản địa hoá nào khác vì ký hiệu và cấu trúc không thay đổi. Người đọc biết backend Rust vẫn có thể nhận ra mã nguồn Faber vì các từ khoá Latin và thứ tự kiểu-trước tạo nên một diện mạo riêng biệt.

Khai báo đặt kiểu trước#

Faber đặt kiểu trước tên trong mọi khai báo. Đây là điều ngược lại với cú pháp họ C phổ biến, và đó là chủ ý:

Cấu trúcThói quen của họ CFaber
Biếnint count = 0numerus count ← 0
Hàmfn greet(name: String) → Stringfunctio salve(textus nomen) → textus
Tham số(String name)(textus nomen)

Khai báo đặt kiểu trước có nghĩa là hình dạng của dữ liệu là điều đầu tiên người đọc nhìn thấy. Điều này tự nhiên phù hợp với các ngôn ngữ đọc từ trái sang phải theo độ bao quát ngữ nghĩa — khai báo trong tiếng Trung, tiếng Hindi và tiếng Ả Rập cũng theo cùng thứ tự.

hàm divide(số a, số b)  số  rỗng {
    nếu b  0 do_đó trả rỗng
    trả a / b
}

Từ vựng hành vi bằng tiếng Latin#

Faber sử dụng các từ Latin cho mọi cấu trúc có hình dạng hành vi hoặc ngữ pháp. Từ vựng này nhỏ và đều đặn. Nó bắt nguồn từ một nguồn cổ điển duy nhất thay vì có nhiều nguồn từ nguyên pha trộn như trong hầu hết ngôn ngữ lập trình.

Khai báo#

Từ khoáVai tròTương đương gần đúng
functioKhai báo một hàm hoặc phương thức có tênfn, def, function
genusKhai báo một kiểu cụ thể có các trườngclass, struct
implendumKhai báo một hợp đồng hành viinterface, trait
typusKhai báo bí danh kiểutypedef, type
discretioKhai báo một hợp kiểu có thẻenum, sum type

Liên kết và truyền giá trị#

Từ khoáVai tròTương đương gần đúng
fixumLiên kết bất biến (chỉ ghi một lần)let, const
variaLiên kết khả biếnlet mut, var
sitLiên kết bất biến suy luận ngắn gọnlet (suy luận)
reddeTrả về một giá trị từ hàmreturn
iaceNém lỗi qua kênh lỗithrow, raise
moriTrì hoãn — hành vi chưa thể biểu đạtunimplemented!, todo

Luồng điều khiển#

Từ khoáVai tròTương đương gần đúng
siNhánh điều kiệnif
sinNhánh ngược điều kiệnelse if
secusNhánh còn lạielse
dumVòng lặp whilewhile
iteraLặp qua giá trị, khoá hoặc khoảngfor
eligeSo khớp mẫu (nhánh đầu tiên thắng)match, switch
facKhối thử với phục hồi lỗitry, do
capeBộ xử lý lỗi cho faccatch

Từ vựng Latin có thể liên kết — nó được cung cấp trong gói chuẩn nhưng có thể ánh xạ lại thông qua bản địa hoá người đọc. Lập trình viên Thái thấy ถ้า thay cho si; lập trình viên Trung Quốc thấy 函数 thay cho functio. Từ vựng không có đặc quyền; chỉ ngữ pháp là cố định.

Ký hiệu cấu trúc#

Trong khi từ vựng hành vi sử dụng các từ Latin, ý nghĩa cấu trúc sử dụng các ký hiệu phổ quát. Các ký hiệu này không bao giờ được bản địa hoá và không bao giờ thay đổi ý nghĩa giữa các lần kết xuất. Chúng là điểm neo trực quan giúp nhận ra mã nguồn Faber bất kể từ khoá được hiển thị bằng ngôn ngữ nào.

Luồng giá trị#

Ký hiệuÝ nghĩa
Liên kết thời gian chạy, gán lại và biến đổi — toán tử gán duy nhất
Khai báo kiểu giá trị trả về của hàm
Lối thoát thay thế: kiểu kênh lỗi hoặc phục hồi chuyển đổi nội tuyến
Khớp nối đóng — nối thân hàm đóng với chữ ký

Hình dạng kiểu#

Ký hiệuÝ nghĩa
Ghi rõ kiểu tĩnh — khẳng định ở thời điểm biên dịch về kiểu của một giá trị
Chuyển đổi thời gian chạy — phân tích hoặc ép kiểu có thể thất bại
Kiểu hợp nội tuyến — nối hai kiểu (như T ∪ nihil)

So sánh và logic#

Ký hiệuNghĩa
Bằng và khác tuyệt đối — yêu cầu khớp kiểu nghiêm ngặt
< > So sánh thứ tự
¬Logic và bitwise: and, or, xor, not

Quy ước liên kết rất quan trọng#

Một lựa chọn ký hiệu cần được chú ý đặc biệt vì đây là điểm gây nhầm lẫn phổ biến nhất đối với người đọc mới:

Ký hiệuVai tròDùng cho
Luồng thời gian chạyLiên kết ban đầu, gán lại và biến đổi trong thời gian thực thi
=Hình dạng cấu trúcTên trường bên trong literal và siêu dữ liệu khai báo — không dùng để lưu trữ thời gian chạy

Hầu hết ngôn ngữ dùng = cho cả “định nghĩa trường này trong một kiểu” và “đặt một giá trị thời gian chạy vào biến này”. Faber tách hai nhiệm vụ đó. Mọi đều là luồng dữ liệu đang hoạt động; mọi = bên trong Type { … } đều là bố cục trường của 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
}

So với các ngôn ngữ phổ biến#

Bảng dưới đây cho thấy các mẫu lập trình phổ biến ánh xạ thế nào vào hệ thống ba tín hiệu của Faber. Cột Faber sử dụng một ký hiệu hoặc từ khoá khác nhau cho từng nhiệm vụ ngữ nghĩa riêng biệt — không nạp chồng.

Nhiệm vụ ngữ nghĩaPhổ biến trong các ngôn ngữ khácFaber
Khai báo kiểu tham sốname: Stringtextus nomen
Kiểu giá trị trả về→ String, : String textus
Gán thời gian chạyx = value
Kiểm tra bằng nhau==
Tính có thể rỗngT?, Option<T>T ∪ nihil
Nhánh + một câu lệnhif (cond) return xsi cond ergo redde x
Ép kiểu(T)value, value as Tvalue ∷ T
Chuyển đổi (có thể thất bại)try_into()value ↦ T

Tham khảo#

  1. Ngữ pháp EBNF — danh mục đầy đủ các ký hiệu và từ khoá
  2. examples/corpus/ — kho ngôn ngữ với 292 tệp ví dụ bao phủ mọi từ khoá
  3. examples/corpus/operatores/ — các ví dụ về toán tử và ký hiệu
  4. Các điều răn — chín quy luật thiết kế bảo toàn các tín hiệu này

Canonical vs sugar surfaces#

Nhiều bề mặt có thể phân tích, một hình dạng ngữ nghĩa duy nhất.

Một mẫu thiết kế lặp lại trong Faber: ngôn ngữ định nghĩa một cách viết chuẩn cho mỗi cấu trúc, nhưng chấp nhận nhiều cách viết đường tắt có ngữ nghĩa tương đương. Trình biên dịch không ưu tiên cách nào — cả hai đều được phân tích thành cùng một nút AST. Bộ định dạng quyết định cách viết nào sẽ được xuất ra dựa trên ngữ cảnh và chế độ.

Quy tắc: Các cách viết đường tắt có ngữ nghĩa tương đương với dạng đầy đủ. Nhiều bề mặt được phân tích thành cùng một HirAnnotation hoặc nút kiểu. faber format --canonical ưu tiên cách viết chuẩn; chế độ tác giả giữ nguyên cách viết đường tắt mà tác giả đã dùng.

Đường tắt kiểu số#

Các kiểu số có cách viết chuẩn dạng đầy đủ và các dạng đường tắt nhỏ gọn. Lựa chọn này áp dụng theo từng mô-đun, không phải theo từng kho mã — một gói CLI có thể dùng dạng đầy đủ ở mọi nơi, trong khi một mô-đun nhân tensor dùng dạng đường tắt:

Đường tắtDạng chuẩnMiền
f32, f64, i32, u64fractus<f32>, numerus<i32>Dấu độ rộng — kiểu số vô hướng
tf32, tf32[4], ti64[2, 3]tensor<f32, _>, tensor<f32, [4]>Tensor dày — t + độ rộng + hình dạng tùy chọn
sf32, sf32[2, 3], si64[N]sparsa<f32, _>, sparsa<f32, [2, 3]>Tensor thưa — s + độ rộng + hình dạng tùy chọn
mf32[4, 4], mu32[3, 3]matrix<f32, [4, 4]>Ma trận lớp thanh ghi — m + độ rộng + hình dạng
lf32, lu32, li64lista<f32>, lista<u32>Danh sách — l + độ rộng
f16fractus<f16>Dấu độ rộng half-float (chỉ có ý nghĩa về ngữ nghĩa/bố cục)

Faber thông thường (ưu tiên dạng đầy đủ):

hằng danh_sách<f32> values  tập_rỗng

hằng ten_xo<f32, [2, 3]> grid  tập_rỗng

hằng số<i32> narrow  7

Các mô-đun số (ưu tiên dạng đường tắt):

hằng danh_sách<f32> values  tập_rỗng

hằng ten_xo<f32, [2, 3]> grid  tập_rỗng

hằng số<i32> narrow  7

Đường tắt chỉ dùng ở vị trí kiểu. Các định danh giá trị có tên f32, tf32 hoặc mf32 vẫn giữ nguyên — trình biên dịch chỉ diễn giải chúng là đường tắt khi chúng xuất hiện ở vị trí kiểu. Một tệp sử dụng đường tắt nhất quán nên khai báo điều này một lần ở đầu tệp:

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

Đường tắt chú thích#

Chú thích Faber tuân theo cùng mô hình hai bề mặt như kiểu số. Chú thích là siêu dữ liệu do trình biên dịch sở hữu, được gắn vào các khai báo — chẳng hạn @ optio cho định nghĩa tùy chọn CLI hoặc @ futura cho các hàm bất đồng bộ.

Dạng chuẩn: một bản ghi có ngoặc nhọn với tên trường rõ ràng:

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

Dạng đường tắt: các đối số theo vị trí và bí danh có tên:

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

Cả hai dạng đều tạo ra cùng một bản ghi HirAnnotation. Dạng chuẩn rõ ràng và tự mô tả; dạng đường tắt ngắn gọn cho các chú thích được dùng thường xuyên, khi thứ tự trường đã được quy ước rõ. faber format --canonical ưu tiên các bản ghi có ngoặc nhọn; chế độ tác giả giữ nguyên dạng mà tác giả đã chọn.

Định dạng theo tác giả và dạng chuẩn#

Lệnh faber format hoạt động ở hai chế độ, phản ánh nguyên tắc dạng chuẩn và dạng đường tắt:

Chế độLệnhĐầu vàoĐầu ra
Tác giảfaber formatAST đã phân tích + trivia đứng trướcMã nguồn Faber giữ nguyên chú thích #, dòng trống và cách viết đường tắt
Chuẩnfaber format --canonicalHIR đã phân tích + TypeTableFaber đã chuẩn hóa — không có chú thích, dùng cách viết chuẩn, không có đường tắt

Cả hai chế độ đều đi qua toàn bộ phần đầu của trình biên dịch (phân tích từ vựng, phân tích cú pháp, phân tích ngữ nghĩa đối với chế độ chuẩn). Mã nguồn không hợp lệ sẽ tạo ra chẩn đoán của trình biên dịch — bộ định dạng không âm thầm định dạng đầu vào bị lỗi.

Các quy tắc chính áp dụng cho cả hai chế độ:

  • Thụt lề bốn khoảng trắng
  • Dấu ngoặc Stroustrup: dấu { mở nằm trên cùng dòng với phần đầu điều khiển
  • Chế độ tác giả giữ nguyên sự hiện diện của các dòng trống nhưng thu gọn các chuỗi dài hơn một dòng
  • Chế độ tác giả không chèn các dòng trống mà mã nguồn không có
  • Chế độ chuẩn chuẩn hóa cách viết kiểu về dạng đầy đủ, tensor đường tắt về dạng chuẩn, và chú thích về bản ghi có ngoặc nhọn
  • Chế độ chuẩn xuất T ∪ nihil cho các hợp nullable, và sponte cho các tham số tùy chọn

Nguyên tắc thiết kế#

Mẫu dạng chuẩn và dạng đường tắt xuất hiện ở nhiều nơi vì đây là một nguyên tắc thiết kế có chủ ý, không phải tập hợp các tiện ích riêng lẻ:

MiềnDạng chuẩnĐường tắt
Kiểu sốnumerus<i32>i32
Kiểu tensortensor<f32, [4]>tf32[4]
Chú thích@ optio { binding = verbose }@ optio verbose ...
Định dạngfaber format --canonicalfaber format (chế độ tác giả)
Ngôn ngữ đọcLatin (la)Bất kỳ gói ngôn ngữ nào

Mẫu này phục vụ hai mục tiêu. Thứ nhất, nó hạ thấp rào cản tiếp cận — người dùng mới có thể viết tf32[4] mà không phải gõ tensor<fractus<f32>, [4]>. Thứ hai, nó giữ cho ngôn ngữ chuẩn không mơ hồ — khi độ chính xác quan trọng, dạng đầy đủ nói chính xác ý nghĩa của nó. Bộ định dạng kết nối hai dạng này: tác giả viết dạng đường tắt, người đánh giá có thể yêu cầu dạng chuẩn, và CI có thể thực thi một trong hai.

Tham chiếu#

  1. radix/docs/design/numeric-type-sugar.md — các họ đường tắt đầy đủ, ưu tiên cách viết
  2. radix/docs/design/annotation-sugar.md — mô hình chú thích hai bề mặt
  3. radix/docs/design/faber-canonical-surface.md — chính sách định dạng theo tác giả và dạng chuẩn
  4. faber/docs/EBNF.md — các bảng ngữ pháp cho dạng đường tắt