Ngôn ngữ Starlark

Báo cáo vấn đề Xem nguồn Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Trang này là thông tin tổng quan về Starlark (trước đây gọi là Skylark), ngôn ngữ được dùng trong Bazel. Để xem danh sách đầy đủ các hàm và loại, hãy xem tài liệu tham khảo về Bazel API.

Để biết thêm thông tin về ngôn ngữ này, hãy xem kho lưu trữ GitHub của Starlark.

Để biết quy cách chính thức về cú pháp và hành vi của Starlark, hãy xem Quy cách ngôn ngữ Starlark.

Cú pháp

Cú pháp của Starlark được lấy cảm hứng từ Python3. Đây là cú pháp hợp lệ trong Starlark:

def fizz_buzz(n):
  """Print Fizz Buzz numbers from 1 to n."""
  for i in range(1, n + 1):
    s = ""
    if i % 3 == 0:
      s += "Fizz"
    if i % 5 == 0:
      s += "Buzz"
    print(s if s else i)

fizz_buzz(20)

Ngữ nghĩa của Starlark có thể khác với Python, nhưng sự khác biệt về hành vi rất hiếm, ngoại trừ những trường hợp Starlark gây ra lỗi. Các loại Python sau đây được hỗ trợ:

Khả năng biến đổi

Starlark ưu tiên tính bất biến. Có 2 cấu trúc dữ liệu có thể thay đổi: listdict. Các thay đổi đối với cấu trúc dữ liệu có thể thay đổi, chẳng hạn như thêm giá trị vào danh sách hoặc xoá một mục trong từ điển, chỉ có hiệu lực đối với các đối tượng được tạo trong ngữ cảnh hiện tại. Sau khi một ngữ cảnh kết thúc, các giá trị của ngữ cảnh đó sẽ không thay đổi được.

Lý do là vì các bản dựng Bazel sử dụng tính năng thực thi song song. Trong quá trình tạo bản dựng, mỗi tệp .bzl và mỗi tệp BUILD đều có ngữ cảnh thực thi riêng. Mỗi quy tắc cũng được phân tích trong ngữ cảnh riêng.

Hãy xem xét một ví dụ với tệp foo.bzl:

# `foo.bzl`
var = [] # declare a list

def fct(): # declare a function
  var.append(5) # append a value to the list

fct() # execute the fct function

Bazel tạo var khi foo.bzl tải. Do đó, var là một phần trong ngữ cảnh của foo.bzl. Khi fct() chạy, thao tác này sẽ diễn ra trong ngữ cảnh của foo.bzl. Sau khi quá trình đánh giá cho foo.bzl hoàn tất, môi trường sẽ chứa một mục nhập không thể thay đổi, var, có giá trị [5].

Khi một bar.bzl khác tải các biểu tượng từ foo.bzl, các giá trị đã tải vẫn không thay đổi. Vì lý do này, mã sau đây trong bar.bzl là không hợp lệ:

# `bar.bzl`
load(":foo.bzl", "var", "fct") # loads `var`, and `fct` from `./foo.bzl`

var.append(6)  # runtime error, the list stored in var is frozen

fct()          # runtime error, fct() attempts to modify a frozen list

Bạn không thể thay đổi các biến toàn cục được xác định trong tệp bzl bên ngoài tệp bzl đã xác định các biến đó. Giống như ví dụ trên sử dụng các tệp bzl, các giá trị do quy tắc trả về là bất biến.

Sự khác biệt giữa tệp BUILD và tệp .bzl

Các tệp BUILD đăng ký các mục tiêu bằng cách gọi các quy tắc. Tệp .bzl cung cấp các định nghĩa cho hằng số, quy tắc, macro và hàm.

Hàm gốcquy tắc gốc là các biểu tượng chung trong tệp BUILD. Các tệp bzl cần tải các tệp đó bằng cách sử dụng mô-đun native.

Có 2 quy định hạn chế về cú pháp trong tệp BUILD: 1) khai báo hàm là bất hợp pháp và 2) không được phép dùng các đối số *args**kwargs.

Điểm khác biệt với Python

  • Các biến toàn cục là bất biến.

  • Không được phép dùng câu lệnh for ở cấp cao nhất. Thay vào đó, hãy sử dụng các hàm. Trong tệp BUILD, bạn có thể sử dụng các biểu thức tạo danh sách.

  • Không được phép dùng câu lệnh if ở cấp cao nhất. Tuy nhiên, bạn có thể sử dụng các biểu thức if: first = data[0] if len(data) > 0 else None.

  • Thứ tự xác định để lặp lại qua Từ điển.

  • Không được phép đệ quy.

  • Loại int chỉ được phép có số nguyên có dấu 32 bit. Tràn sẽ báo lỗi.

  • Sửa đổi một tập hợp trong quá trình lặp lại là một lỗi.

  • Ngoại trừ các kiểm thử về tính bằng nhau, các toán tử so sánh <, <=, >=, >, v.v. không được xác định trên các kiểu giá trị. Tóm lại: 5 < 'foo' sẽ gây ra lỗi và 5 == "5" sẽ trả về giá trị false.

  • Trong bộ giá trị, dấu phẩy ở cuối chỉ hợp lệ khi bộ giá trị nằm giữa dấu ngoặc đơn – khi bạn viết (1,) thay vì 1,.

  • Các ký tự cố định trong từ điển không được có khoá trùng lặp. Ví dụ: đây là một lỗi: {"a": 4, "b": 7, "a": 1}.

  • Các chuỗi được biểu thị bằng dấu ngoặc kép (chẳng hạn như khi bạn gọi repr).

  • Chuỗi không thể lặp lại.

Các tính năng sau của Python không được hỗ trợ:

  • ghép chuỗi ngầm ẩn (sử dụng toán tử + tường minh).
  • So sánh theo chuỗi (chẳng hạn như 1 < x < 5).
  • class (xem hàm struct).
  • import (xem tuyên bố load).
  • while, yield.
  • các loại float và set.
  • trình tạo và biểu thức trình tạo.
  • is (thay vào đó, hãy dùng ==).
  • try, raise, except, finally (xem fail để biết lỗi nghiêm trọng).
  • global, nonlocal.
  • hầu hết các hàm tích hợp, hầu hết các phương thức.