Ngôn ngữ Starlark

Báo cáo sự cố Xem nguồn

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

Để 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 thông số kỹ thuật có căn cứ của cú pháp và hành vi Starlark, hãy xem Thông số kỹ thuật 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ừ các trường hợp mà Starlark đưa ra lỗi. Các loại Python sau đây được hỗ trợ:

Khả năng thay đổi

Starlark ưa chuộng tính bất biến. Có 2 cấu trúc dữ liệu có thể thay đổi: danh sáchchính tả. 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 một giá trị vào một danh sách hoặc xoá một mục nhập trong từ điển chỉ hợp lệ đố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 thể thay đổi.

Lý do là các bản dựng Bazel sử dụng phương thức thực thi song song. Trong một bản dựng, mỗi tệp .bzl và mỗi tệp BUILD sẽ có ngữ cảnh thực thi riêng. Mỗi quy tắc cũng được phân tích theo ngữ cảnh riêng.

Hãy xem qua 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, nó sẽ thực hiện việc đó trong ngữ cảnh foo.bzl. Sau khi quá trình đánh giá foo.bzl hoàn tất, môi trường sẽ chứa một mục không thể thay đổi là var với giá trị [5].

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

# `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 các tệp bzl bên ngoài tệp bzl đã xác định các biến đó. Cũng giống như ví dụ trên về cách sử dụng tệp bzl, các giá trị do quy tắc trả về là không thể thay đổi.

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

Tệp BUILD đăng ký mục tiêu thông qua việc thực hiện lệnh gọi đến các quy tắc. Tệp .bzl cung cấp thông tin đị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 ký hiệu chung trong tệp BUILD. Các tệp bzl cần tải các tệp này bằng mô-đun native.

Có 2 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 sử dụng đối số *args**kwargs.

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

  • Biến toàn cục là không thể thay đổi.

  • Không được phép sử dụng câu lệnh for ở cấp cao nhất. Hãy sử dụng chúng trong các hàm. Trong tệp BUILD, bạn có thể sử dụng tính năng hiểu danh sách.

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

  • Thứ tự xác định cho việc lặp lại thông qua Từ điển.

  • Không được phép lặp lại.

  • Loại số nguyên được giới hạn ở số nguyên 32 bit đã ký. Trường hợp tràn sẽ tạo ra lỗi.

  • Việc 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 phép kiểm thử bằng nhau, các toán tử so sánh <, <=, >=, >, v.v. không được xác định trên các loại giá trị. Tóm lại: 5 < 'foo' sẽ gửi một lỗi và 5 == "5" sẽ trả về false.

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

  • Hằng từ điển không được có khoá trùng lặp. Ví dụ: đây là lỗi: {"a": 4, "b": 7, "a": 1}.

  • 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 Python sau đây không được hỗ trợ:

  • nối chuỗi ngầm ẩn (sử dụng toán tử + tường minh).
  • Thông tin so sánh theo chuỗi (chẳng hạn như 1 < x < 5).
  • class (xem hàm struct).
  • import (xem câu lệnh load).
  • while, yield.
  • độ chính xác đơn và kiểu tập hợp.
  • 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.