שפת הכוכב

דף זה הוא סקירה כללית על Starlark, שנקרא בעבר Skylark, השפה שבה נעשה שימוש בבזל. רשימה מלאה של הפונקציות והסוגים מופיעה בחומר העזר של API ב-Bazel.

למידע נוסף על השפה, יש לעיין במאגר GitHub של Starlark.

לקבלת המפרט המוסמך של תחביר והתנהגות של Starlark, ניתן לעיין במפרט השפה של Starlark.

תחביר

התחביר של Starlark בהשראת Python3. זהו תחביר חוקי בסטארלארק:

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 תומכת בחוסר קדימות. יש שני מבני נתונים שניתן לשנות אותם: רשימות וביטויים. שינויים במבני נתונים הניתנים לשינוי, כגון הוספת ערך לרשימה או מחיקת ערך במילון, תקפים רק עבור אובייקטים שנוצרו בהקשר הנוכחי. כשההקשר מסתיים, הערכים שלו משתנים.

הסיבה לכך היא ש-Bazel builds לשימוש מקביל. במהלך build, כל קובץ .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 קבצים: 1) הצהרה על פונקציות היא בלתי חוקית, ו-2) *args ו-**kwargs ארגומנטים אינם מותרים.

הבדלים עם Python

  • משתנים גלובליים אינם משתנים.

  • for הצהרות אינן מותרות ברמה העליונה. כדאי להשתמש בהם בתוך פונקציות במקום. ב-BUILD קבצים אפשר להשתמש בתובנות של רשימות.

  • if הצהרות אינן מותרות ברמה העליונה. עם זאת, ניתן להשתמש ב-if ביטויים first = data[0] if len(data) > 0 else None:

  • סדר דטרטיבי של מילונים.

  • לא ניתן להגדיר שימוש חוזר.

  • סוג הרכיב מוגבל למספרים שלמים חתומים של 32 סיביות. גלישה תגרום לשגיאה.

  • שינוי אוסף במהלך חזרה הוא שגיאה.

  • פרט לבדיקות של שוויון, אופרטורים של השוואה <, <=, >=, > וכו' לא מוגדרים בכל סוגי הערכים. בקצרה: 5 < 'foo' תחזיר שגיאה ו-5 == "5" תחזיר FALSE.

  • ב-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.
  • רוב הפונקציות המובנות, רוב השיטות.