A superfície é o contrato
O que um módulo exporta, com que aridade e com que tipos — e por que mudá-la é o mesmo problema que quebrar uma ABI.
Numa linguagem compilada, quebrar a ABI é trocar o layout de uma struct ou a convenção de chamada. O sintoma é cruel: o programa carrega e corrompe memória, longe da causa e sem nada denunciar.
Aqui não há layout binário a quebrar. E existe exatamente o mesmo problema, com outro nome.
| Na linguagem compilada | Aqui |
|---|---|
símbolo removido do .so | símbolo tirado do relay |
| assinatura trocada | aridade, nome ou tipo de parâmetro trocado |
| layout de struct mudado | campo acrescentado a um record |
| tipo de retorno trocado | o mesmo — e ele atravessa o adopt |
soname bump | versão maior no forge.toml |
O que é contrato, e o que não é#
A superfície respeita o relay. Um módulo que declara o que exporta está dizendo que o resto é interno — e o que é interno não é contrato, então mexer nele não quebra ninguém.
lib.df — o relay decide
action somar(a: Integer, b: Integer) -> Integer:
yield a + b
action interna(): // nao esta no relay: nao e contrato
yield 1
record Ponto:
x: Integer
y: Integer
relay somar, PontoSem relay, tudo o que é de topo é contrato — o que é a escolha certa para um arquivo que não declarou nada, e um bom motivo para declarar.
A superfície, como dado#
dataforge
adopt Arcane.Abi as Abi
// Abi.superficie("lib.df") devolve, por simbolo:
// especie acao, record, blueprint, enum, trait, valor
// minimo quantos argumentos ele EXIGE
// maximo quantos ele ACEITA (void = variadico)
// parametros os nomes, na ordem — e eles sao contrato
// tipos o tipo declarado de cada um
// retorno o tipo de retorno, que atravessa o adopt
// campos de um record ou blueprint
// linha onde ele foi declarado
assert len(keys(Abi.regras())) bigger_eq 7