Esta página é uma visão geral do Starlark, antes 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 Starlark no GitHub.
Para 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 em 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 da do Python, mas as diferenças de comportamento são raras, exceto nos casos em que o Starlark gera um erro. Os seguintes tipos de Python são compatíveis:
Mutabilidade
O Starlark favorece a imutabilidade. Duas estruturas de dados mutáveis estão disponíveis: listas e dicionários. As 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 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.
Vamos conferir 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. Assim, var
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 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 isso, 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 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.
As funções nativas e as regras nativas são símbolos globais em arquivos
BUILD
. Os arquivos bzl
precisam ser carregados usando o módulo native
.
Há duas restrições sintáticas em arquivos BUILD
: 1) declarar funções é ilegal e 2) argumentos *args
e **kwargs
não são permitidos.
Diferenças com Python
As variáveis globais são imutáveis.
As instruções
for
não são permitidas no nível superior. Em vez disso, use-as em funções. Em arquivosBUILD
, você pode usar comprehensions de lista.As instruções
if
não são permitidas no nível superior. No entanto, é possível usar expressõesif
: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 valores. Em resumo:5 < 'foo'
vai gerar um erro e5 == "5"
vai retornar "false".Em tuplas, uma vírgula à direita é válida apenas quando a tupla está entre parênteses. Por exemplo,
(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.
Os seguintes recursos do Python não são compatíveis:
- 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 declaraçãoload
).while
,yield
.- tipos de ponto flutuante e conjunto.
- geradores e expressões de gerador.
is
(use==
).try
,raise
,except
,finally
(consultefail
para erros fatais).global
,nonlocal
.- a maioria das funções e métodos integrados.