Esta página é uma visão geral do Starlark, antes conhecida 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 o idioma, consulte o repositório do GitHub do Starlark.
Para a especificação oficial da sintaxe do Starlark e do usuário, consulte a Especificação de 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. O código Python a seguir têm suporte:
Mutabilidade
Starlark favorece a imutabilidade. Duas estruturas de dados mutáveis estão disponíveis: lists 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 é concluído, os valores dele se tornam imutáveis.
Isso ocorre porque as versões do Bazel usam a execução paralela. Durante um build, cada arquivo .bzl
e BUILD
recebe o próprio contexto de execução. Cada regra também é
analisados 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
faz parte do contexto de
foo.bzl
. Quando fct()
é executado, isso ocorre no contexto de foo.bzl
. Depois
a avaliação de foo.bzl
for concluída, o ambiente terá 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 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
Variáveis globais definidas em arquivos bzl
não podem ser alteradas fora da
bzl
que as definiu. Assim como o exemplo acima usando arquivos bzl
,
valores retornados pelas regras são imutáveis.
Diferenças entre arquivos BUILD e .bzl
Arquivos BUILD
registram destinos fazendo chamadas para regras. .bzl
arquivos fornecem
definições de constantes, regras, macros e funções.
Funções nativas e regras nativas são símbolos globais em
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
As variáveis globais são imutáveis.
Não são permitidas instruções
for
no nível superior. Use-as em funções. Em arquivosBUILD
, é possível usar compreensões de lista.As instruções
if
não são permitidas 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 em testes de igualdade, os operadores de comparação
<
,<=
,>=
,>
etc. são não definidos em nenhum tipo de valor. Resumindo:5 < 'foo'
vai gerar um erro e5 == "5"
vai retornar "falso".Em tuplas, uma vírgula final é válida apenas 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).
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 instruçãoload
).while
,yield
.- tipos flutuantes e de conjuntos.
- geradores e expressões de gerador.
is
(use==
).try
,raise
,except
,finally
(consultefail
para erros fatais).global
,nonlocal
.- a maioria das funções integradas e a maioria dos métodos.