Esta página é uma visão geral do Starlark, anteriormente conhecido como Skylark, a linguagem usada no Bazel. Para uma lista completa de funções e tipos, consulte a referência da API Bazel.
Para mais informações sobre a linguagem, consulte o repositório do GitHub do Starlark.
Para conferir a especificação oficial da sintaxe e do comportamento do Starlark, consulte a especificação da linguagem Starlark.
Sintaxe
A sintaxe do 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 de Python são compatíveis:
Mutabilidade
Starlark favorece a imutabilidade. Duas estruturas de dados mutáveis estão disponíveis: listas e dicionários. 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 é concluído, os valores dele se tornam imutáveis.
Isso ocorre porque os builds do Bazel usam a execução paralela. Durante um build, cada arquivo .bzl
e cada arquivo BUILD
recebem o próprio contexto de execução. Cada regra também é
analisada no 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
faz parte do contexto de
foo.bzl
. Quando fct()
é executado, isso acontece no contexto de foo.bzl
. Depois
que a avaliação de foo.bzl
for concluída, o ambiente vai conter uma entrada imutável,
var
, com o valor [5]
.
Quando outro bar.bzl
carrega símbolos de foo.bzl
, os valores carregados permanecem
imutáveis. Por esse motivo, o código a seguir 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 no exemplo acima que usa arquivos bzl
,
os valores retornados pelas regras são imutáveis.
Diferenças entre arquivos BUILD e .bzl
Os arquivos BUILD
registram as metas fazendo chamadas para regras. Os arquivos .bzl
fornecem
definições de constantes, regras, macros e funções.
As funções nativas e as 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 como
ilegais e 2) os argumentos *args
e **kwargs
não são permitidos.
Diferenças com o Python
As variáveis globais são imutáveis.
As instruções
for
não são permitidas no nível superior. Use-as em funções. Em arquivosBUILD
, é possível usar 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 iterar dicionários.
A recursão não é permitida.
O tipo int é limitado a números inteiros assinados de 32 bits. Os estouros 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 em tipos de valor. Em resumo:5 < 'foo'
vai gerar um erro e5 == "5"
vai retornar falso.Nas tuplas, uma vírgula à direita é válida somente quando a tupla 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 com 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 de string implícita (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 flutuantes e de conjuntos.
- geradores e expressões de gerador.
is
(use==
).try
,raise
,except
,finally
(consultefail
para ver erros fatais).global
,nonlocal
.- a maioria das funções integradas e a maioria dos métodos.