3 điểm bởi GN⁺ 2023-07-19 | 1 bình luận | Chia sẻ qua WhatsApp
  • Hylo hướng tới lập trình hệ thống và lập trình generic an toàn dựa trên ngữ nghĩa giá trị; trình biên dịch và thư viện chuẩn vẫn ở giai đoạn đầu, nhưng có thể chạy thử ví dụ trên Compiler Explorer
  • Nghiên cứu ngôn ngữ tập trung vào các chủ đề như mở rộng inout projection cho subscript của Swift, method bundles, đồng thời có cấu trúc, và danh sách liên kết đôi dựa trên ngữ nghĩa giá trị
  • Trình biên dịch sử dụng LLVM, đồng thời nghiên cứu biên dịch generic có coherence, cache/tuần tự hóa trạng thái chương trình, và khả năng tương tác với C
  • Môi trường phát triển cung cấp extension VSCode, trình biên dịch tài liệu, nguyên mẫu Language Server; hỗ trợ SPM/CMake, Ninja/Xcode, Windows/Linux/macOS và image Docker cho toolchain phát triển
  • Các ví dụ làm lộ rõ quy tắc sở hữu và giải phóng ở mức mã thông qua projection an toàn và sink method, cho thấy một ngôn ngữ hệ thống có thể cưỡng chế tính an toàn như thế nào

Phạm vi và trạng thái hiện tại của Hylo

  • Trình biên dịch và thư viện chuẩn của Hylo hiện vẫn ở giai đoạn đầu
  • Có thể chạy thử các ví dụ mã Hylo nâng cao trên Compiler Explorer
  • Ngay ở màn hình đầu tiên cũng có liên kết để thử Hylo trên Compiler Explorer

Ngữ nghĩa giá trị và nghiên cứu ngôn ngữ

Trình biên dịch và thư viện chuẩn

  • Công việc về trình biên dịch trải rộng trên biên dịch dựa trên LLVM, generic, lưu trạng thái, và khả năng tương tác với C
    • Biên dịch bằng LLVM
    • Kỹ thuật mới để biên dịch generic có coherence
    • Cache và tuần tự hóa trạng thái chương trình của trình biên dịch
    • Nghiên cứu C interop
  • Về phía thư viện chuẩn, hiện đã công bố tài liệu triển khai hiện tại và các công việc liên quan đến thuật toán collection

Trải nghiệm nhà phát triển và môi trường build

  • Cung cấp kèm các công cụ cho editor, tài liệu và language server
  • Môi trường build và phát triển hỗ trợ nhiều hệ điều hành và quy trình dựa trên container
    • Hỗ trợ Development Containers để rút ngắn quy trình bắt đầu
    • Hỗ trợ SPM/CMake, Ninja/Xcode, Windows/Linux/macOS
    • Plugin trình biên dịch để sinh test
    • Image Docker Hylo development toolchain đã build sẵn
    • Trình biên dịch được viết bằng Swift 6.2

Nghiên cứu và tài liệu thuyết trình liên quan đến Hylo

Ví dụ mã: projection an toàn và giải phóng tường minh

  • Ví dụ Subscripts - A Safe Projection Mechanism cho thấy cấu trúc trong đó kiểu Angle lưu giá trị radians và cung cấp property degrees bằng các khối letinout
    • let của degrees chuyển đổi radians sang degree rồi trả về
    • inout phơi bày giá trị degree tạm thời d bằng yield &d, rồi chuyển giá trị đã thay đổi trở lại radians và phản ánh vào self.radians
    • main lấy projection bằng inout d = &a.degrees, đổi d thành 0.0, rồi kiểm tra a.radians == 0.0
  • Ví dụ Sink Methods - Capability for Deinitializing có cấu trúc trong đó kiểu Computer cung cấp shutdown() như một sink method
    • shutdown() in nội dung bộ nhớ rồi xử lý self.ram theo kiểu sink
    • test1 tạo Computer nhưng không shutdown nên phát sinh Cannot deinit computer
    • test2 chỉ shutdown bên trong if random_bool(), nên trên nhánh không đi vào if sẽ phát sinh Cannot deinit computer
    • test3 nếu gọi shutdown bên trong while thì sau vòng lặp đầu tiên sẽ phát sinh vấn đề sử dụng consumed object, còn trên đường đi không vào while thì vẫn còn lỗi không thể deinit
  • Có thể xem thêm ví dụ trong compiler test suite

1 bình luận

 
GN⁺ 2023-07-19
Ý kiến trên Hacker News
  • Với tư cách là người kế nhiệm C++, có lẽ Val còn đáng mong đợi hơn cả CppFront xuất sắc của Herb Sutter. Tôi mới chỉ xem hai bài thuyết trình bên dưới, nhưng có vẻ các điểm cốt lõi là biên dịch tĩnh, kiểu tĩnh, tương tác với C++, an toàn bộ nhớ, an toàn kiểu và không có tranh chấp dữ liệu.
    Khi giải thích, tôi thường nói: “Giả sử bắt đầu một dự án C++ mới và tạm coi như không cần bận tâm đến hiệu năng; nếu mọi thứ đều được truyền bằng giá trị và trả về bằng giá trị, không dùng con trỏ hay tham chiếu, thì chẳng phải sẽ tốt vì không phải lo về tác dụng phụ hay tranh chấp dữ liệu sao?” Điều thú vị ở Val là dù loại bỏ con trỏ và tham chiếu khỏi ngôn ngữ, trình biên dịch vẫn có thể áp dụng nội bộ việc truyền bằng tham chiếu const và tối ưu hóa giá trị trả về, nhờ đó giữ được cả ngữ nghĩa mong muốn lẫn hiệu năng.
    Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
    https://cppcast.com/val-and-mutable-value-semantics/

    • Nên nghe hai tập gần đây của ADSP Podcast trong đó Sean Parent nói về Val. Adobe Research Labs đang tài trợ phát triển khá nghiêm túc.
      https://adspthepodcast.com/
    • “Tương tác với C++” nghe đáng ngờ. Khó tin một ngôn ngữ khác có thể tương tác đúng nghĩa với C++; ngay cả giữa các trình biên dịch C++ với nhau cũng có thể mất tương thích nhị phân, và đôi khi giữa các phiên bản của cùng một trình biên dịch cũng khác nhau.
    • Nghe như một mô hình đặt quá nhiều niềm tin vào trình biên dịch. Tôi lo rằng chỉ một thay đổi nhỏ có thể phá vỡ tối ưu hóa ở một đoạn mã nằm xa, làm hỏng hiệu năng.
    • Nếu “cả ngày truyền bằng giá trị và trả về bằng giá trị” thì sẽ không còn dễ sửa đổi hay lưu trữ tham chiếu bên trong struct một cách hiệu quả. Nếu chương trình cần bất kỳ cấu trúc dữ liệu nào hơi phi tiêu chuẩn hoặc phức tạp, đây có vẻ là một ràng buộc chí mạng. Tất nhiên, xét đến việc triển khai đúng các cấu trúc dữ liệu như vậy vốn khó, điều này cũng có thể lại là ưu điểm.
    • Tôi đã viết các chương trình PHP thực tế theo kiểu này trong vài năm, cứ truyền mảng qua lại mà không phải bận tâm.
      Tôi nghĩ trình thông dịch PHP thực ra đủ thông minh để dùng copy-on-write (sao chép khi ghi), nhưng tôi chưa từng tự profiling. Dù vậy, kể cả khi xử lý dữ liệu khá phức tạp, phân tích DSL từng ký tự, sinh SQL động, rồi nhào nặn kết quả thành cấu trúc tùy ý trong mỗi lần tải trang, tôi cũng không cảm thấy có vấn đề hiệu năng.
      Thời PHP 4, object cũng hoạt động như giá trị được lưu trong biến; về sau khi biến object được đổi sang ngữ nghĩa tham chiếu, tôi cho rằng việc không biến “giá trị, tham chiếu biến, con trỏ tới giá trị” thành thuộc tính của biến trực giao với kiểu lưu trữ là một cơ hội bị bỏ lỡ đáng tiếc.
      $a = $b; // sao chép giá trị của $b vào $a
      $a = &$b; // $a và $b giờ là cùng một biến
      $a = *$b; // $a trỏ tới cùng object với $b, nhưng khác với $a = &$b, bản thân biến không bị liên kết với nhau
  • Một mặt, thật tốt khi có nhiều ngôn ngữ trừu tượng hóa không tốn chi phí xuất hiện như vậy, nhưng tôi cũng mong các lập trình viên hệ thống giờ chọn ra một kẻ thắng cuộc. Tôi không muốn cộng đồng lập trình viên hệ thống vốn đã nhỏ lại bị chia nhỏ hơn nữa thành Rust, Zig, Val, v.v.; mong cuộc chiến ngôn ngữ hệ thống sớm kết thúc.

    • Có lẽ chính vì đã chọn một ngôn ngữ quá sớm nên lĩnh vực này thiếu đổi mới quá lâu. Tôi hoan nghênh cuộc chiến.
    • Ở thời điểm hiện tại, tôi xem Rust là người thắng. Vì nó đã vượt qua rào cản khổng lồ là thực sự được đưa vào kernel Linux và Windows. Theo nghĩa đó, giờ có vẻ không còn nhiều không gian cho một ngôn ngữ hệ thống mới chen vào.
    • Tôi không nghĩ mọi chuyện sẽ thành như vậy. Vì thế càng có thêm lý do để mở rộng hỗ trợ wasm + wasi ở khắp nơi.
  • Dòng cảm xúc của tôi khi lần đầu biết đến Val hôm nay là như thế này: “Ồ, một ngôn ngữ hệ thống mới. Có thể chẳng có gì đặc biệt, nhưng cứ xem thử. Tài liệu ổn đấy. Các ý tưởng về ownership khá được suy nghĩ kỹ, cú pháp cũng hợp lý. Nhưng liệu nó có đủ khác biệt để có lý do tồn tại riêng không? Ai làm nó vậy?”
    Rồi khi thấy Dave Abrahams đang làm dự án này, tôi bắt đầu quan tâm hơn. Tôi từng gặp ông ấy ở Apple và cũng nhớ bài thuyết trình Crusty về Swift[1]. Tôi thích các quan điểm mạnh mẽ trong đó, nhưng sau này Apple đã gỡ video đó xuống với lý do có một số lời khuyên đã cũ. Giờ ông ấy ở Adobe, nên tôi tự hỏi đây có phải là ngôn ngữ của Adobe không.
    Kết luận là đáng để theo dõi, và sau khi xem bài thuyết trình được liên kết thì cứ chờ xem.
    [1] Tôi đã tìm thấy bài thuyết trình Crusty: "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ

    • David Abrahams đã là một contributor rất quan trọng của Boost từ trước khi vào Apple, là thành viên ủy ban C++ và là người ủng hộ mạnh mẽ lập trình generic kiểu Stepanov. Việc ông ấy tham gia dự án Val không có gì đáng ngạc nhiên.
  • Với tư cách là nhà phát triển trình biên dịch, tôi đã bị sốc khi thấy các issue dưới đây
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    Có mùi là trạng thái triển khai không tốt. Cần tự host càng sớm càng tốt, và khi đó họ sẽ tìm ra thêm nhiều lỗi cơ bản kiểu này. Vậy mà vẫn có hơn 500 sao

    • Nhìn từ góc độ một nhà phát triển trình biên dịch khác, hiếm có sai lầm nào gây hại như tự host quá sớm. Dù ngôn ngữ có thể mang lại lợi ích ròng cho các chương trình nhỏ và vừa, để phù hợp với một dự án lớn như trình biên dịch và có đủ công cụ hỗ trợ thì cần lâu hơn nhiều. May là họ không vội
    • Nếu những lỗi như vậy nằm trong một trình biên dịch đang vận hành thì đáng lo, nhưng nếu là trình biên dịch của một ngôn ngữ vẫn đang được định nghĩa thì không đến mức là vấn đề lớn. So sánh Rust 1.0 và 1.71 sẽ thấy khoảng cách giữa “bản ổn định đầu tiên” và “trình biên dịch của một ngôn ngữ ổn định được dùng nhiều trong thực tế” lớn đến thế nào
      Tự host cũng không phải là tất cả. Trên hết, nó gần với một cột mốc mang tính biểu tượng; đạt được thì đáng chúc mừng, nhưng tôi không nghĩ nên xem đó là điểm yếu của ngôn ngữ cho đến tận khá muộn trong chu kỳ phát triển
    • Bản thân Swift đến giờ cũng chưa tự host, dù sắp ra bản 6. Tôi không phải nhà phát triển trình biên dịch, nhưng kết luận của các cuộc thảo luận quanh chủ đề này trong cộng đồng Swift là hiện vẫn chưa đáng làm
  • Tôi đã trì hoãn việc “nghịch Val” từ lâu, hôm nay cuối cùng cũng thử, nhưng dù đã có hơn 4.000 commit, nó vẫn còn rất xa trạng thái có thể dùng được. Phần lớn ví dụ trong phần giới thiệu ngôn ngữ không biên dịch được, và cả những ví dụ nhìn bề ngoài đơn giản cũng thất bại
    Carbon thì vẫn chưa thực sự tung ra được thứ gì ra hồn, còn Sean Baxter đang đạt nhiều tiến triển với trình biên dịch Circle và cũng đã triển khai khá nhiều điểm hay của Carbon. Nếu còn khó gọi là một ngôn ngữ thì cũng khó trở thành người kế nhiệm

  • Giờ đã có V, Val, Vala, Vale. Còn ngôn ngữ nào khác mà tôi quên không?

    • Còn có VAL nữa. Một ngôn ngữ từ thập niên 80, đã ảnh hưởng đến Haskell thông qua SISAL. Tuy nhiên có lẽ ngoài cộng đồng ngôn ngữ song song thì không nhiều người biết đến VAL đó
    • Tên giống nhau lại có thể trở thành lợi thế. Người học những ngôn ngữ kiểu này nhiều khả năng đang tìm “thứ mới đang hot”, và họ cũng có thể biết rồi tìm hiểu thêm các ngôn ngữ khác có tên tương tự. JavaScript cũng từng như vậy, mà kết quả cũng không tệ
    • Tôi cứ tưởng đây thật sự là Vale. Việc trùng tên khá đáng tiếc
    • Thêm nữa, V cũng được gọi là Vlang, và Vale trước đây cũng từng được gọi là Vlang
  • Chuyện này lần nào cũng được nhắc tới, nhưng điều duy nhất tôi không thích ở Val là ValeV cũng đều là ngôn ngữ hệ thống mới. Vì tên gọi mà cả ba quá dễ bị nhầm với nhau

    • Còn có Vala nữa. Phạm vi hơi khác, nhưng vẫn là một ngôn ngữ có tên tương tự
    • Tôi đã phải bấm vào link để kiểm tra xem đây là ngôn ngữ projection hay ngôn ngữ region
    • Còn có VAL: Variable Assembly Language nữa https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • Có bài liên quan. Còn bài nào nữa không?
    Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - tháng 6 năm 2022, 19 bình luận

  • Tôi đã đọc lướt paper “mutable value semantics”, và tự hỏi liệu hiểu rằng các tác giả đề xuất thay thế tham chiếu và con trỏ bằng a) một phần indirection và kiểm tra runtime thông qua cấu trúc lồng nhau cùng Any, b) chỉ số mảng, có đúng không
    Đoạn “Việc hỏi làm sao có thể biểu diễn các cấu trúc dữ liệu tự tham chiếu như danh sách liên kết đôi hay đồ thị có hướng bằng kiểu giá trị khả biến là hợp lý. Thực ra, đồ thị bất kỳ có thể được biểu diễn bằng danh sách kề…” làm tôi chú ý. Tôi không thấy rõ cách triển khai danh sách liên kết đôi một cách hợp lý mà không tạo lại heap bộ nhớ và một dạng garbage collection nào đó bên trong phần triển khai
    Ngoài ra, tôi tìm thấy thảo luận tại https://github.com/orgs/val-lang/discussions/736, và có vẻ sẽ xuất hiện một lối thoát kiểu unsafe của Rust. Như vậy mọi vấn đề sẽ được giải quyết, nhưng câu hỏi “chỉ với tập con an toàn của Val có đủ để tạo ứng dụng thực dụng hay không” có lẽ sẽ còn là chủ đề tranh luận trong thời gian dài

    • Nếu dùng mảng và dùng chỉ số mảng thay cho con trỏ, thực ra bạn có thể tái tạo bộ nhớ
      Lý do cách này ít ngớ ngẩn hơn tưởng tượng là các chỉ số này bị ràng buộc với một cấu trúc dữ liệu cụ thể, chẳng hạn danh sách liên kết đôi hay đồ thị, nên không dễ thao túng để truy cập nơi khác trong chương trình. Điều đó đúng cả khi trình biên dịch kiểm tra việc này, lẫn khi có nỗ lực phá chương trình
  • Tôi không biết nên hiểu phần giải thích trong ví dụ trên trang chủ như thế nào. Nó viết rằng: “Không xảy ra cấp phát không cần thiết. Kết quả của longer_of là projection của đối số dài hơn, nên khi emphasize thay đổi z thì giá trị y được thay đổi trực tiếp. Giá trị không bị sao chép hay di chuyển, nhưng cũng không được truyền cho emphasize dưới dạng tham chiếu”
    Đây là tình huống đối số chuỗi được truyền vào hàm và có ký tự được nối thêm vào, nhưng chuỗi hiện có hẳn đã có độ dài ban đầu cùng một vị trí và kích thước cụ thể trên stack; tôi không hiểu làm sao có thể làm vậy mà không tạo bản sao mới của y. Có phải họ chừa phần đệm dư ở cuối chuỗi để phòng trường hợp ai đó nối thêm không? Nếu vậy thì chừa bao nhiêu, và tại sao nhìn chung lại không kém hiệu quả hơn?

    • Tiền tố bốn dấu cách không phải để trích dẫn mà dùng cho khối mã/khối chữ monospace. Trên HN, người ta thường dùng quy ước > để trích dẫn, và nó vẫn hoạt động tốt dù parser không xử lý đặc biệt
    • Giá trị bất biến không nhất thiết phải nằm trên stack
      Tuy vậy tôi cũng có thắc mắc tương tự. Nếu sửa một chuỗi 1GB thì chuyện gì xảy ra? Có phải copy-on-write không?
      Trong 99% trường hợp có thể bị tối ưu hóa biến mất, nhưng tôi có cảm giác 1% còn lại sẽ gây ra suy giảm hiệu năng rất khó tìm
    • Tự trả lời sau vài ngày thì có vẻ có thể làm được nếu âm thầm shadow tên biến đã thay đổi bằng một giá trị mới dài hơn trên stack. Có lẽ đây cũng có thể là ý nghĩa của “projection”. Trong trường hợp này stack đã được cấp phát sẵn nên không xảy ra cấp phát mới. Tôi không phải chuyên gia về ngôn ngữ hay compiler, nên có thể thuật ngữ này vốn đã quen thuộc trong lĩnh vực đó
    • Bên dưới có giải thích thêm. longer_of không phải là hàm mà là subscript, và subscript không trả về giá trị mà projection giá trị để cấp cho caller quyền truy cập đọc/ghi tạm thời
      Tôi không rõ điều này không được xem là di chuyển như thế nào. Với chuỗi, để cho phép kích thước thay đổi như Rust, có thể nó được đặt trên heap