Esta página apresenta uma visão geral do Starlark, anteriormente conhecido como Skylark, a linguagem usada no Bazel. Para ver uma lista completa de funções e tipos, consulte a Referência da API Bazel (link em inglês).
Para saber mais sobre a linguagem, consulte o repositório do Starlark no GitHub (link em inglês).
Para conferir a especificação oficial da sintaxe e do comportamento do Starlark, consulte a Especificação da linguagem Starlark.
Sintaxe
A sintaxe de Starlark é inspirada no Python3. Esta é uma sintaxe válida no 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)
A semântica do Starlark pode ser diferente do Python, mas as diferenças comportamentais são raras, exceto nos casos em que o Starlark gera um erro. Os seguintes tipos do Python são compatíveis:
Mutabilidade
Starlark favorece a imutabilidade. Duas estruturas de dados mutáveis estão disponíveis: listas e dicts. Mudanças em estruturas de dados mutáveis, como anexar um valor a uma lista ou excluir uma entrada em um dicionário, são válidas apenas para objetos criados no contexto atual. Depois que um contexto termina, os valores dele se tornam imutáveis.
Isso ocorre porque as versões do Bazel usam execução paralela. Durante a criação, cada arquivo
.bzl
e cada arquivo BUILD
recebem o próprio contexto de execução. Cada regra também é
analisada em seu próprio contexto.
Vejamos um exemplo com o arquivo 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
O Bazel cria var
quando foo.bzl
é carregado. var
, portanto, faz parte do contexto
de foo.bzl
. Quando fct()
é executado, ele faz isso no contexto de foo.bzl
. Depois que a avaliação de foo.bzl
for concluída, o ambiente conterá uma entrada imutável, var
, com o valor [5]
.
Quando outra bar.bzl
carrega símbolos de foo.bzl
, os valores carregados permanecem
imutáveis. Por esse motivo, o seguinte código em bar.bzl
é 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
As variáveis globais definidas em arquivos bzl
não podem ser alteradas fora do arquivo bzl
que as definiu. Assim como o exemplo acima usando arquivos bzl
, os valores retornados pelas regras são imutáveis.
Diferenças entre arquivos BUILD e .bzl
Os arquivos BUILD
registram destinos fazendo chamadas para regras. Os arquivos .bzl
fornecem
definições para constantes, regras, macros e funções.
Funções nativas e regras nativas são símbolos globais em
arquivos BUILD
. Os arquivos bzl
precisam carregá-los usando o módulo native
.
Há duas restrições sintáticas em arquivos BUILD
: 1) declarar funções é
ilegal e 2) os argumentos *args
e **kwargs
não são permitidos.
Diferenças com o Python
Variáveis globais são imutáveis.
Não são permitidas instruções
for
no nível superior. Use-os nas funções. Em arquivosBUILD
, você pode usar as compreensões de lista.Não são permitidas instruções
if
no nível superior. No entanto, as expressõesif
podem ser usadas:first = data[0] if len(data) > 0 else None
.Ordem determinística para iteração nos dicionários.
A recursão não é permitida.
O tipo int é limitado a números inteiros assinados de 32 bits. Overflows vão gerar um erro.
Modificar uma coleção durante a iteração é um erro.
Exceto para testes de igualdade, os operadores de comparação
<
,<=
,>=
,>
etc. não são definidos entre os tipos de valor. Resumindo:5 < 'foo'
gerará um erro e5 == "5"
retornará falso.Em tuplas, uma vírgula à direita é válida apenas quando ela está entre parênteses, quando você escreve
(1,)
em vez de1,
.Os literais de dicionário não podem ter chaves duplicadas. Por exemplo, este é um erro:
{"a": 4, "b": 7, "a": 1}
.As strings são representadas por aspas duplas (como quando você chama repr).
As strings não são iteráveis.
Não há suporte para os seguintes recursos do Python:
- concatenação implícita de strings (use o operador
+
explícito). - Comparações encadeadas (como
1 < x < 5
). class
(consulte a funçãostruct
).import
(consulte a instruçãoload
).while
,yield
.- tipos de flutuação e definição.
- geradores e expressões geradoras.
is
(use==
).try
,raise
,except
,finally
. Consultefail
para ver erros fatais.global
,nonlocal
.- da maioria das funções integradas e dos métodos.