系統程式語言 Nim 2.2.6 正式發布。此次更新距離 2.2.4 版本發布已有六個月,包含 141 個提交,修復了多個 bug 並提升了效能。 Nim 是一種靜態型別、編譯式程式語言,其文法靈感源自 Python,並具備類似 Lisp 的元程式設計能力。它可以編譯成 C、C++ 和 JavaScript,在提供 C 級效能的同時,也兼具高階語言的表達能力。此專案的代碼採用 MIT 許可證。
Nim 的主要特性包括:強大的巨集系統,可在編譯時操作抽象語法樹 (AST);豐富的泛型程式設計系統,包含多種概念、多重分派、支援多種策略(ARC/ORC、refc、標記清除)的確定性記憶體管理、內建的 async/await 非同步程式支援,以及便於與 C/C++/JavaScript 整合的 FFIFI。 Nim 定位為系統語言,適用於從嵌入式系統到 Web 開發的各種應用。服務器重點在於效率、記憶體安全性和開發人員的便利性。
關鍵變化:
- 針對物件欄位的移動語意最佳化。編譯器已學會辨識在傳回物件欄位時可以使用移動操作的情況。以前,類似「return obj.field」這樣的結構會導致資料複製;現在編譯器會正確應用移動操作:proc getField(obj: MyObject): string = return obj.field # 現在使用移動而不是複製
對於大數據類型(字串、序列、包含資源的物件)來說,這一點尤其重要,因為消除不必要的複製可以在不改變程式碼的情況下顯著提高效能。
- 完全重寫了帶有異常處理的閉包迭代器。閉包迭代器的轉換機制已完全重寫,顯著提高了具有異常處理的非同步程式碼的穩定性。修正了關鍵問題,包括在非頂層使用 try/except 時導致的 SIGSEGV 錯誤:`iterator problematicIterator(): int {.closure.} = for i in 0..10: try: if i == 5: raise newException(Error, "pexValueError, "Ncepty
閉包迭代器內部 finally 程式碼區塊中異常傳播不正確的問題也已解決。
- 修復了與記憶體管理相關的問題
- 垃圾回收器處理循環資料結構時的一個根本性問題已修復。該問題可能導致“非法儲存存取”錯誤。此問題自該語言誕生之初就已存在,並在具有相互引用的複雜物件圖中表現得尤為突出。
- 修正了物件銷毀順序錯誤的問題,該錯誤可能導致存取已釋放的記憶體:type Resource = object data: ptr Data Container = object resource: Resource other: OtherResource # 現在析構函數以正確的順序呼叫:# 首先是 other,然後是 resource
- ORC編譯器錯誤地將一些閉包環境標記為循環,導致記憶體釋放延遲或洩漏。現在循環分析已修復。
- 修正了 asyncnet 在 TLS 連線協商錯誤時的套接字洩漏問題:proc handleClient() {.async.} = var socket = await server.accept() try: await socket.setupSSL() # 如果此處外洩,套接字現在可以正確關機
- 編譯器中的關鍵修復。
- 修正了一個迴歸問題,該問題導致在帶有靜態參數的過程內部宣告的全域變數在每次呼叫時都會重新初始化:proc test[N: static int]() = var global {.global.}: array[N, int] global[0] += 1 echo gtestlotest.}: array[N, int] global[0] += 1 echo gtestlotest[0] testlotest(應該輸出:2,但實際輸出:1(被重新初始化了)
- 修正了遞歸函數中全域變數的程式碼產生問題,該問題會導致未定義行為。
- 修正了在轉換器中使用全域變數建構子時產生無效 C 程式碼的舊問題:`converter toInt(x: MyType): int = let global {.global.} = MyType() # 產生無效 C 程式碼 result = global.value`
- 修正了在某些情況下拋出 Defect 異常並使用 doAssert 時編譯器崩潰的問題。
- 類型系統的改進
- 修正了無法從 case/if 表達式傳回 lent 值的問題:proc getBest(a, b: string): lent string = if a.len > b.len: return a # 之前:編譯錯誤 else: return b
- 修正了泛型類型中 lent 欄位值保存不正確的問題:type Wrapper[T] = object data: lent T proc process[T](w: Wrapper[T]) = echo w.data # 現在值已正確儲存
- 恢復了對帶有 requiresInit 的類型的結果變數的初始化檢查,該檢查在 2.2 版本中存在問題:type MustInit {.requiresInit.} = object value: int proc test(): MustInit = discard # 現在可以正確拋出未初始化結果的錯誤
- 修正了忽略基底類型不可複製屬性(`.noCopy`)的問題:`type Base {.noCopy.} = object Derived = object of Base var a: Derived var b = a # 現在正確地禁止了
- 效能最佳化
- 對簡單類型的「@」運算子進行了加速:消除了從簡單類型數組創建序列時出現的嚴重性能下降問題:`let arr = [1, 2, 3, 4, 5] let s = @arr` # 之前速度極慢,現在已達到最優。
- vmgen.sameConstant 的最佳化:透過最佳化常數比較,編譯速度顯著提升。 虛擬機 編譯器和記憶體分配操作的減少。
- 在單一表達式中解引用類型轉換的結果不再會導致不必要的複製:`let data = cast[ptr MyType](address)[]` # 現在是無複製的
- 後端特定修復
- JavaScript的
- =destroy 對於非 var 類型:修正了先前導致編譯錯誤的析構函數產生問題。
- cast[char] for values > 255: 現在能夠正確地執行截斷,就像在 C 後端一樣。
- 可變參數中的概念:修正了在可變參數中傳遞概念時出現的「內部錯誤」。
- C++:恢復了 2.2.2 和 2.2.4 版本之間回歸導致的相容類型的左值特性問題:# nim cpp var x: CppCompatibleType takeRef(x) # 再次作為左值工作
- C(參考)
- 在某些平台上的 pthread:修正了使用 .abi 的 pthread_mutex_t 的程式碼產生問題;
- 帶有 GC 記憶體的泛型:修正了為包含託管記憶體的泛型類型產生錯誤 C 程式碼的問題;
- JavaScript的
- 虛擬機
- 全域變數與賦值:對編譯時全域變數的處理進行了多項修復。
- 來自 compileTime 過程的 case 物件:修正了將 case 物件作為靜態參數傳遞的問題。
- repr 用於 repc 下的長字串:修正了使用 repr 時的 RangeDefect。
- 標準庫中的修復
- strutils.formatSize 中處理接近 int64.high 的大值的問題已修復:echo formatSize(9223372036854775807) # 現在結果正確
- 在雙端佇列中,專案迭代器的行為已恢復,以相容於 2.0.16 和 2.2.0 版本。
- 在 lists.SinglyLinkedList.remove 中,修正了從單鍊錶中刪除元素時出現的 AssertionDefect。
- 在 tables.withValue 中,已修正 withValue 巨集中針對不可變表格的檢查條件。
- 實用性和範圍
- 修正了對帶有 raise 的 push 編譯指示忽略詞法作用域的錯誤,錯誤發生在 "{.push raises: [].}" 中。
- 修正了在 pragma 程式碼區塊之外禁用警告的「洩漏」效應:{.push warning[UnusedImport]: off.} import module1 {.pop.} import module2 # 現在警告已正確啟用
- 其他重要修復
- cstring 比較:為 cstring 新增了缺少的「<」和「cmp」運算子。
- 浮點數範圍檢查:已啟用浮點數的正確範圍檢查。
- filterIt 和 rvalue:修正了錯誤地回傳 rvalue 而不是 lvalue 的問題
- 修正了編譯時比較指標時出現的欄位缺陷。
- 複製類型描述符後 hasCustomPragma:複製類型描述符後功能已恢復。
- nim 文件和私有欄位:修正了私有欄位中的註解對公用欄位的使用問題。
來源: opennet.ru
