Esta página es una descripción general de Starlark, antes conocido como Skylark, el idioma utilizado en Bazel. Para obtener una lista completa y tipos de atributos, consulta la referencia de la API de Bazel.
Para obtener más información sobre el lenguaje, consulta el repositorio de GitHub de Starlark.
Para la especificación autorizada de la sintaxis de Starlark y consulta la especificación de lenguaje de Starlark.
Sintaxis
La sintaxis de Starlark está inspirada en Python3. La siguiente sintaxis es válida en 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)
La semántica de Starlark puede diferir de la de Python, pero las diferencias de comportamiento son es poco frecuente, excepto en los casos en los que Starlark genera un error. Los siguientes comandos tipos compatibles:
Mutabilidad
Starlark favorece la inmutabilidad. Hay dos estructuras de datos mutables disponibles: lists y dicts. Cambios en mutable de datos estructurados, como agregar un valor a una lista o borrar una entrada de diccionario son válidos solo para los objetos creados en el contexto actual. Después de un finaliza el contexto, sus valores se vuelven inmutables.
Esto se debe a que las compilaciones de Bazel usan la ejecución paralela. Durante una compilación, cada .bzl
y cada archivo BUILD
obtiene su propio contexto de ejecución. Cada regla también es
analizar en su propio contexto.
Veamos un ejemplo con el archivo 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 crea var
cuando se carga foo.bzl
. var
forma parte de foo.bzl
'
adicional. Cuando se ejecuta fct()
, lo hace dentro del contexto de foo.bzl
. Después del
se completa la evaluación de foo.bzl
, el entorno contiene una entrada inmutable
var
, con el valor [5]
.
Cuando otro bar.bzl
carga símbolos de foo.bzl
, los valores cargados permanecen
inmutable. Por este motivo, el siguiente código de bar.bzl
es ilegal:
# `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
Las variables globales definidas en archivos bzl
no se pueden cambiar fuera de
bzl
que las definió. Al igual que en el ejemplo anterior con archivos bzl
,
los valores que devuelven las reglas son inmutables.
Diferencias entre los archivos BUILD y .bzl
Los archivos BUILD
registran objetivos mediante llamadas a reglas. Los archivos .bzl
proporcionan
definiciones de constantes, reglas, macros y funciones.
Las funciones nativas y las reglas nativas son símbolos globales en
BUILD
. Los archivos bzl
deben cargarlos con el módulo native
.
Hay dos restricciones sintácticas en los archivos BUILD
: 1) Declarar funciones es
ilegal, y 2) los argumentos *args
y **kwargs
no están permitidos.
Diferencias con Python
Las variables globales son inmutables.
No se permiten sentencias
for
en el nivel superior. Úsalas dentro de las funciones en su lugar. En los archivosBUILD
, puedes usar la comprensión de listas.No se permiten sentencias
if
en el nivel superior. Sin embargo, las expresionesif
se pueden utilizar:first = data[0] if len(data) > 0 else None
.Orden determinista de la iteración a través de Diccionarios.
No se permite la recurrencia.
El tipo int está limitado a números enteros firmados de 32 bits. Los desbordamientos arrojarán un error.
Modificar una colección durante la iteración es un error.
Excepto en el caso de las pruebas de igualdad, los operadores de comparación
<
,<=
,>=
,>
, etc. sin definir en los tipos de valores. En resumen:5 < 'foo'
arrojará un error y5 == "5"
mostrará un valor falso.En tuplas, una coma final es válida solo cuando la tupla está entre paréntesis, cuando escribes
(1,)
en lugar de1,
.Los literales de diccionario no pueden tener claves duplicadas. Por ejemplo, esta es una error:
{"a": 4, "b": 7, "a": 1}
.Las cadenas se representan con comillas dobles (como cuando se llama repr).
Las cadenas no son iterables.
Las siguientes funciones de Python no son compatibles:
- concatenación de cadenas implícita (usa un operador
+
explícito) - Comparaciones en cadena (como
1 < x < 5
) class
(consulta la funciónstruct
).import
(consulta la sentenciaload
).while
,yield
.- float y set_type.
- ni expresiones de generación.
is
(usa==
en su lugar).try
,raise
,except
,finally
(consultafail
para ver errores irrecuperables).global
,nonlocal
.- la mayoría de las funciones integradas, la mayoría de los métodos.