ภาษาสตาร์ลาร์ก

รายงานปัญหา ดูแหล่งที่มา

หน้านี้คือภาพรวมของ Starlark หรือเดิมชื่อ Skylark เป็นภาษาที่ใช้ใน Bazel ดูรายการฟังก์ชันและประเภททั้งหมดได้ที่เอกสารอ้างอิง Bazel API

ดูข้อมูลเพิ่มเติมเกี่ยวกับภาษานี้ได้ที่ที่เก็บ GitHub ของ Starlark

สำหรับข้อกำหนดเฉพาะของไวยากรณ์และลักษณะการทำงานของ Starlark โปรดดูข้อกำหนดภาษาของ Starlark

ไวยากรณ์

ไวยากรณ์ของ Starlark ได้รับแรงบันดาลใจมาจาก Python3 นี่คือไวยากรณ์ที่ถูกต้องใน 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)

อรรถศาสตร์ของ Starlark อาจแตกต่างจาก Python แต่ความแตกต่างด้านพฤติกรรมนั้นพบได้น้อยมาก ยกเว้นกรณีที่ Starlark ทำให้เกิดข้อผิดพลาด ระบบรองรับประเภท Python ต่อไปนี้

การเปลี่ยนแปลง

Starlark ชอบความไม่เปลี่ยนแปลง มีโครงสร้างข้อมูลที่เปลี่ยนแปลงได้ 2 แบบ ได้แก่ รายการและคำสั่ง การเปลี่ยนแปลงโครงสร้างข้อมูลที่เปลี่ยนแปลงได้ เช่น การต่อท้ายค่าลงในรายการหรือการลบรายการในพจนานุกรมจะใช้ได้กับออบเจ็กต์ที่สร้างขึ้นในบริบทปัจจุบันเท่านั้น หลังจากสิ้นสุดบริบทแล้ว ค่าของบริบทจะเปลี่ยนแปลงไม่ได้

เนื่องจากบิลด์ของ Bazel ใช้การดำเนินการพร้อมกัน ในระหว่างบิลด์ ไฟล์ .bzl แต่ละไฟล์และไฟล์ BUILD แต่ละไฟล์จะมีบริบทการดำเนินการของตัวเอง แต่ละกฎจะได้รับการวิเคราะห์ ในบริบทของตัวเองด้วย

ลองดูตัวอย่างที่มีไฟล์ 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 สร้าง var เมื่อ foo.bzl โหลด var จึงเป็นส่วนหนึ่งของบริบทของ foo.bzl เมื่อ fct() ทำงาน ก็จะทำงานภายในบริบทของ foo.bzl หลังจากการประเมินสำหรับ foo.bzl เสร็จสมบูรณ์แล้ว สภาพแวดล้อมจะมีรายการที่เปลี่ยนแปลงไม่ได้ var พร้อมด้วยค่า [5]

เมื่อ bar.bzl อื่นโหลดสัญลักษณ์จาก foo.bzl ค่าที่โหลดจะไม่เปลี่ยนแปลง ด้วยเหตุนี้ โค้ดต่อไปนี้ใน bar.bzl จึงผิดกฎหมาย:

# `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

จะเปลี่ยนแปลงตัวแปรร่วมที่กําหนดไว้ในไฟล์ bzl นอกไฟล์ bzl ที่กําหนดไว้ไม่ได้ เช่นเดียวกับตัวอย่างด้านบนที่ใช้ไฟล์ bzl ค่าที่กฎแสดงผลจะเปลี่ยนแปลงไม่ได้

ความแตกต่างระหว่างไฟล์ BUILD และไฟล์ .bzl

กำหนดเป้าหมายไฟล์ BUILD รายการผ่านการเรียกใช้กฎ ไฟล์ .bzl ให้คำจำกัดความสำหรับค่าคงที่ กฎ มาโคร และฟังก์ชัน

ฟังก์ชันเนทีฟและกฎเนทีฟเป็นสัญลักษณ์ส่วนกลางในไฟล์ BUILD bzl ไฟล์ต้องโหลดโดยใช้โมดูล native

ไฟล์ BUILD มีข้อจํากัดด้านไวยากรณ์ 2 ประการ ได้แก่ 1) การประกาศว่าฟังก์ชันผิดกฎหมาย และ 2) ไม่อนุญาตให้ใช้อาร์กิวเมนต์ *args และ **kwargs

ความแตกต่างกับ Python

  • ตัวแปรร่วมจะเปลี่ยนแปลงไม่ได้

  • ไม่อนุญาตให้ใช้ข้อความ for ที่ระดับบนสุด ให้ใช้แท็กภายในฟังก์ชัน แทน ในไฟล์ BUILD คุณอาจใช้ความเข้าใจแบบรายการ

  • ไม่อนุญาตให้ใช้ข้อความ if ที่ระดับบนสุด แต่ใช้นิพจน์ if ได้: first = data[0] if len(data) > 0 else None

  • ลำดับที่กำหนดสำหรับทำซ้ำผ่านพจนานุกรม

  • ไม่อนุญาตให้ใช้คำซ้ำ

  • ประเภท Int จะจำกัดอยู่ที่จำนวนเต็มแบบมีเครื่องหมาย 32 บิต ส่วนเกินจะทำให้เกิดข้อผิดพลาด

  • การแก้ไขคอลเล็กชันในระหว่างการทำซ้ำถือเป็นข้อผิดพลาด

  • ไม่ได้กำหนดโอเปอเรเตอร์การเปรียบเทียบ <, <=, >=, > ฯลฯ ไว้ในประเภทค่า ยกเว้นการทดสอบความเท่ากัน กล่าวโดยสรุปคือ 5 < 'foo' จะแสดงข้อผิดพลาดและ 5 == "5" จะแสดงผลเป็นเท็จ

  • ใน Tuple คอมมาต่อท้ายจะใช้ได้เมื่อ Tuple อยู่ระหว่างวงเล็บเท่านั้น เมื่อคุณเขียน (1,) แทนที่จะเป็น 1,

  • ลิเทอรัลพจนานุกรมต้องไม่มีคีย์ซ้ำกัน ตัวอย่างเช่น นี่คือข้อผิดพลาด: {"a": 4, "b": 7, "a": 1}

  • สตริงจะแสดงเป็นเครื่องหมายอัญประกาศคู่ (เช่น เมื่อคุณเรียกใช้ repr)

  • สตริงเป็นแบบทำซ้ำไม่ได้

ระบบไม่รองรับฟีเจอร์ Python ต่อไปนี้

  • การต่อสตริงโดยนัย (ใช้โอเปอเรเตอร์ + ที่ชัดเจน)
  • การเปรียบเทียบแบบเชน (เช่น 1 < x < 5)
  • class (ดูฟังก์ชัน struct)
  • import (ดูคำสั่งของ load)
  • while, yield
  • จำนวนลอยตัวและประเภทการตั้งค่า
  • เครื่องมือสร้างและนิพจน์เครื่องมือสร้าง
  • is (ใช้ == แทน)
  • try, raise, except, finally (ดูข้อผิดพลาดร้ายแรงได้ที่ fail)
  • global, nonlocal
  • ที่มีในตัวส่วนใหญ่