asset facing PBS addressable
This commit is contained in:
parent
e905055cb0
commit
6150493e95
@ -31,6 +31,8 @@ Os pontos estáveis já conhecidos são:
|
|||||||
|
|
||||||
- packer/runtime tratam `asset_id` como identidade estável;
|
- packer/runtime tratam `asset_id` como identidade estável;
|
||||||
- `asset_name` ainda é a superfície mais natural para autoria e tooling;
|
- `asset_name` ainda é a superfície mais natural para autoria e tooling;
|
||||||
|
- o packer já mantém um `PackerRuntimeSnapshot` coerente em memória como projeção operacional do workspace ativo;
|
||||||
|
- Studio já consome leituras normais a partir desse snapshot operacional em vez de reconstituir a verdade diretamente do filesystem a cada interação;
|
||||||
- o pipeline executável hoje já exige disciplina explícita de stack;
|
- o pipeline executável hoje já exige disciplina explícita de stack;
|
||||||
- a família `19` reforçou a direção de compiler-owned lowering e publication protocol, reduzindo espaço para ambiguidades “aceitas pelo frontend, rejeitadas mais tarde”.
|
- a família `19` reforçou a direção de compiler-owned lowering e publication protocol, reduzindo espaço para ambiguidades “aceitas pelo frontend, rejeitadas mais tarde”.
|
||||||
|
|
||||||
@ -39,14 +41,190 @@ Isso sugere um princípio comum:
|
|||||||
- a linguagem pode continuar amigável na superfície,
|
- a linguagem pode continuar amigável na superfície,
|
||||||
- mas o compiler precisa assumir explicitamente o trabalho de normalizar essa superfície para um contrato executável estável.
|
- mas o compiler precisa assumir explicitamente o trabalho de normalizar essa superfície para um contrato executável estável.
|
||||||
|
|
||||||
|
O novo ponto importante é que, para referências a asset, essa “superfície amigável” não precisa nascer de nomes soltos escritos manualmente nem de arquivos tipados gerados sem owner claro.
|
||||||
|
|
||||||
|
Ela pode ser tratada como uma projeção simbólica derivada da autoridade operacional já existente no packer:
|
||||||
|
|
||||||
|
- `PackerRuntimeSnapshot` como fonte operacional coerente do conjunto de assets visíveis;
|
||||||
|
- Studio como host capaz de sintetizar uma superfície tipada a partir desse snapshot;
|
||||||
|
- PBS como consumidor dessa superfície simbólica;
|
||||||
|
- compiler como responsável por lowerar essa superfície para identidade estável de runtime.
|
||||||
|
|
||||||
|
O entendimento atual desta discussão mudou um ponto importante do modelo anterior:
|
||||||
|
|
||||||
|
- `asset_name` não parece justificar existência como campo operacional separado;
|
||||||
|
- o dado estrutural realmente útil já está no root do asset dentro de `assets/`;
|
||||||
|
- portanto a superfície simbólica candidata pode ser o próprio address normatizado derivado do diretório, e não um nome livre fornecido pelo autor.
|
||||||
|
|
||||||
|
Exemplo de direção:
|
||||||
|
|
||||||
|
- asset root em disco: `assets/some/dir/maluco/asset/asset.json`
|
||||||
|
- superfície simbólica projetada para código/tooling: `assets.some.dir.maluco.asset`
|
||||||
|
|
||||||
|
Na direção atual, essa superfície não deve ser tratada como enum flat simples.
|
||||||
|
|
||||||
|
O modelo preferido é:
|
||||||
|
|
||||||
|
- `assets` como árvore hierárquica sintetizada de compile;
|
||||||
|
- nós intermediários como namespaces de compile;
|
||||||
|
- apenas folhas correspondentes a asset roots reais como valores terminais do tipo `Addressable`.
|
||||||
|
|
||||||
|
Exemplo:
|
||||||
|
|
||||||
|
- `assets.ui` pode ser apenas namespace;
|
||||||
|
- `assets.ui.borders` pode ser apenas namespace;
|
||||||
|
- `assets.ui.borders.panel` pode ser uma folha `Addressable`.
|
||||||
|
|
||||||
|
Isso implica uma regra estrutural importante:
|
||||||
|
|
||||||
|
- um asset terminal não pode ocupar um prefixo que também precise funcionar como namespace para outros assets.
|
||||||
|
|
||||||
|
Exemplo inválido:
|
||||||
|
|
||||||
|
- existir asset terminal em `assets/ui`
|
||||||
|
- e também existir asset terminal em `assets/ui/borders/panel`
|
||||||
|
|
||||||
|
porque `assets.ui` não pode ser simultaneamente `Addressable` terminal e namespace.
|
||||||
|
|
||||||
|
Operational note:
|
||||||
|
|
||||||
|
- Studio should prevent creation of a new asset root when that path would collide with an existing asset terminal/namespace boundary.
|
||||||
|
- In practice, if an asset already exists at a path, Studio should not allow creating descendant assets under that same terminal path.
|
||||||
|
- Likewise, if descendants already exist, Studio should not allow creating a new asset at their prefix path.
|
||||||
|
- This must become an explicit Studio-side creation and move constraint, not just a compiler-side validation concern.
|
||||||
|
|
||||||
|
Nesse modelo:
|
||||||
|
|
||||||
|
- Studio mostra o address normatizado do asset, não um `asset_name` livre;
|
||||||
|
- packer não precisa mais ler nem escrever `asset_name` como variável operacional em `asset.json`;
|
||||||
|
- packer apenas reconhece, normaliza e publica o address derivado do root do asset sem persistir esse address como estado redundante em disco;
|
||||||
|
- `asset_id` permanece como primary key operacional estável do asset dentro do packer/runtime;
|
||||||
|
- o `address` passa a ser a identidade simbólica usada pelos compiladores para referenciar o asset em superfícies de autoria/compile;
|
||||||
|
- renomear ou mover diretório muda o address e quebra referências em compile time;
|
||||||
|
- tooling de rename/move pode existir para amortecer esse custo, mas a quebra deixa de ser ambígua e passa a ser explícita.
|
||||||
|
|
||||||
|
Com esse contexto, o coração real da discussão de asset references não é mais “nome versus `asset_id`”.
|
||||||
|
|
||||||
|
O ponto central passa a ser:
|
||||||
|
|
||||||
|
- como PBS/SDK transforma um `address` autoral em `asset_id` operacional.
|
||||||
|
|
||||||
|
Exemplo de shape ainda ilustrativo:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
fn load(addressable: Addressable, bankRef: BankRef) -> LoadError
|
||||||
|
```
|
||||||
|
|
||||||
|
A dúvida principal não é o nome exato da API, mas o lugar da resolução:
|
||||||
|
|
||||||
|
- a função do SDK recebe um símbolo/valor addressable e resolve internamente para `asset_id`;
|
||||||
|
- ou o próprio `Addressable` já é uma declaração/superfície sintetizada a partir do modelo vindo do backend, carregando a resolução necessária antes mesmo de entrar na função;
|
||||||
|
- ou ainda existe uma terceira forma híbrida em que a superfície autoral é simbólica, mas o lowering do compiler reescreve a chamada para a variante já normalizada em `asset_id`.
|
||||||
|
|
||||||
|
Essa decisão é o núcleo arquitetural da agenda porque define:
|
||||||
|
|
||||||
|
- o quanto a API pública do SDK continua “asset-address-first”;
|
||||||
|
- o quanto o compiler participa do lowering antes da chamada;
|
||||||
|
- e qual parte do sistema é owner da ponte entre identidade simbólica de compile e identidade operacional de runtime.
|
||||||
|
|
||||||
|
O modelo que hoje parece mais coerente com PBS não é colocar essa resolução no corpo de um `declare service`.
|
||||||
|
|
||||||
|
O desenho mais alinhado com a linguagem atual é:
|
||||||
|
|
||||||
|
- `declare service` público continua sendo wrapper ergonômico normal;
|
||||||
|
- a metadata reservada de lowering fica no `declare host`, junto do próprio contrato host-backed;
|
||||||
|
- o compiler consome essa metadata ao baixar a chamada host-backed;
|
||||||
|
- o parâmetro marcado como asset-facing é resolvido de `Addressable` para `asset_id` durante o lowering.
|
||||||
|
|
||||||
|
Exemplo ilustrativo:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare host low_assets {
|
||||||
|
[Host(module = "assets", name = "preload", version = 1)]
|
||||||
|
[AssetLowering(param = 0)]
|
||||||
|
fn preload(addressable: Addressable, bank_id: int) -> LoadError;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare service Assets {
|
||||||
|
fn load(addressable: Addressable, bank: BankRef) -> LoadError {
|
||||||
|
return low_assets.preload(addressable, bank.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Neste desenho:
|
||||||
|
|
||||||
|
- o `service` não contém lógica especial de resolução;
|
||||||
|
- ele só encaminha a chamada de forma autoral/ergonômica;
|
||||||
|
- a assinatura host-backed explicita qual parâmetro sofre asset-lowering;
|
||||||
|
- o compiler sabe exatamente onde injetar o `asset_id` porque a própria assinatura `declare host` carrega o contrato;
|
||||||
|
- o lowering ocorre antes da forma final host/syscall, sem exigir placeholder artificial no corpo do `service`.
|
||||||
|
|
||||||
|
Outro limite arquitetural precisa ficar explícito:
|
||||||
|
|
||||||
|
- `asset` não é a superfície correta para endereçamento de recursos internos;
|
||||||
|
- o `asset` entra como unidade de instalação/publicação/carregamento;
|
||||||
|
- o acesso a internos só faz sentido depois que o conteúdo foi instalado em um `bank` de runtime;
|
||||||
|
- portanto, members internos pertencem à superfície do `bank` e não à superfície do `asset`.
|
||||||
|
|
||||||
|
Isso impede uma confusão comum:
|
||||||
|
|
||||||
|
- `assets.foo.bar` parece sugerir que `bar` é membro estável do asset em si;
|
||||||
|
- mas, neste modelo, `bar` só deve existir como símbolo depois que um `bank` específico expõe esse espaço de endereçamento.
|
||||||
|
|
||||||
|
Como diferentes bancos têm semânticas distintas (`tile bank`, `sound bank`, e futuros bancos), o endereçamento de internos é family-specific e provavelmente pertence a uma spec transversal de runtime/banks, não à política básica de asset references.
|
||||||
|
|
||||||
|
Também surge uma separação importante entre pipeline de compile e runtime packer:
|
||||||
|
|
||||||
|
- o frontend PBS não deveria consultar o packer diretamente para descobrir a superfície de assets;
|
||||||
|
- a estrutura simbólica de assets deve chegar ao compile como dado já preparado na borda backend/orquestradora;
|
||||||
|
- isso significa que o backend de compile precisa transportar para o frontend PBS uma projeção dos assets visíveis;
|
||||||
|
- essa mesma porta abre precedente para outras estruturas futuras entrarem no frontend via request de compile, em vez de acoplá-lo a serviços externos em tempo de frontend.
|
||||||
|
|
||||||
|
For the current agenda scope, the minimum compile projection is intentionally small:
|
||||||
|
|
||||||
|
- `address`
|
||||||
|
- `asset_id`
|
||||||
|
|
||||||
|
No richer asset payload is required yet for this policy discussion.
|
||||||
|
|
||||||
|
Outro recorte importante:
|
||||||
|
|
||||||
|
- preload já existe e não é o objeto principal desta agenda;
|
||||||
|
- ele pode ser citado como contexto de integração;
|
||||||
|
- mas a discussão aqui não é “como preload funciona”;
|
||||||
|
- a discussão é “como asset references em PBS/SDK se resolvem até o ponto em que o caminho low-level já opera com `asset_id`”.
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- [ ] Referências a asset devem permanecer nomeadas na superfície PBS, mesmo se o lowering resolver parte delas para identidade estável?
|
- [ ] Referências a asset devem permanecer nomeadas na superfície PBS, mesmo se o lowering resolver parte delas para identidade estável?
|
||||||
|
- [ ] A superfície simbólica de asset em PBS deve ser derivada explicitamente do `PackerRuntimeSnapshot` mantido pelo packer para o projeto ativo?
|
||||||
|
- [ ] O enum ou namespace sintético derivado de assets pertence ao Studio como host/tooling, ao packer como serviço, ou a uma fronteira compartilhada formalizada entre ambos?
|
||||||
|
- [ ] `asset_name` deve ser removido como variável operacional e substituído pelo address normatizado derivado do root do asset?
|
||||||
|
- [ ] Studio deve adotar esse address como identidade primária visível ao usuário em vez de exibir um nome livre fornecido pelo autor?
|
||||||
|
- [ ] O address simbólico canônico deve ser derivado do path relativo em `assets/` segmentado como namespace (`assets.foo.bar.baz`)?
|
||||||
|
- [ ] A superfície `assets...` deve ser normatizada como árvore hierárquica com namespaces intermediários e folhas terminais `Addressable`, em vez de enum flat?
|
||||||
|
- [ ] A plataforma deve proibir colisões onde um asset terminal também precisaria atuar como namespace-prefixo de outros assets?
|
||||||
|
- [ ] A projeção de assets consumida pelo frontend PBS deve entrar pelo backend no request de compile, em vez de o frontend consultar diretamente o packer?
|
||||||
|
- [ ] Quais outras estruturas além de assets podem, no futuro, seguir esse mesmo padrão de entrada BE -> FE no compile?
|
||||||
|
- [ ] A resolução de `address` para `asset_id` acontece dentro da função pública do SDK, no tipo/símbolo sintetizado (`Addressable` ou equivalente), ou no lowering do compiler antes da chamada?
|
||||||
|
- [ ] Se existir um tipo público como `Addressable`, ele representa só a superfície simbólica autoral ou já embute a identidade operacional necessária para a chamada low-level?
|
||||||
|
- [ ] A API pública do SDK deve permanecer centrada em argumentos simbólicos (`address`, `Addressable`) mesmo quando o backend final consome `asset_id`?
|
||||||
|
- [ ] O compiler deve reescrever chamadas de SDK asset-facing para formas normalizadas por `asset_id`, mantendo a superfície autoral intacta?
|
||||||
|
- [ ] Como separar, normativamente, a superfície de referência ao `asset` da futura superfície de endereçamento dos members expostos por um `bank` após instalação?
|
||||||
|
- [ ] Esse contrato de members expostos por `bank` deve viver em spec transversal (`vm-arch`/runtime surface) em vez de ficar embutido na política de asset references do PBS?
|
||||||
- [ ] O descarte de retorno ignorado deve ser uma regra geral de `expression statement`, ou uma exceção localizada para certos callsites?
|
- [ ] O descarte de retorno ignorado deve ser uma regra geral de `expression statement`, ou uma exceção localizada para certos callsites?
|
||||||
- [ ] Até onde PBS quer empurrar “surface ergonomics, compiler normalization” como princípio geral para APIs de jogo?
|
- [ ] Até onde PBS quer empurrar “surface ergonomics, compiler normalization” como princípio geral para APIs de jogo?
|
||||||
- [ ] Quais casos precisam continuar dinâmicos em runtime e portanto não podem ser lowered agressivamente em compile time?
|
- [ ] Quais casos precisam continuar dinâmicos em runtime e portanto não podem ser lowered agressivamente em compile time?
|
||||||
- [ ] Devemos publicar warnings opcionais para retorno ignorado ou rename-fragile asset references, ou isso fica fora do escopo inicial?
|
- [ ] Devemos publicar warnings opcionais para retorno ignorado ou rename-fragile asset references, ou isso fica fora do escopo inicial?
|
||||||
|
|
||||||
|
Open questions still considered active after the current discussion:
|
||||||
|
|
||||||
|
- [ ] Qual é o shape mínimo e normativo do modelo de assets entregue ao compile/LSP além de `address` e `asset_id`, se algum enriquecimento futuro se mostrar necessário?
|
||||||
|
- [ ] Quais outras estruturas além de assets podem, no futuro, seguir esse mesmo padrão de entrada BE -> FE no compile?
|
||||||
|
- [ ] O descarte de retorno ignorado deve virar warning geral de `expression statement` com valor, ou warning apenas para superfícies específicas?
|
||||||
|
- [ ] Quais casos, além de disponibilidade em runtime, realmente precisam permanecer dinâmicos e fora da resolução estática baseada no snapshot?
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
### Option A - Keep Surface Simple, Keep Runtime Rules Visible
|
### Option A - Keep Surface Simple, Keep Runtime Rules Visible
|
||||||
@ -82,13 +260,113 @@ O ponto central desta discussão é definir o limite dessa política:
|
|||||||
- quando PBS só normaliza lowering,
|
- quando PBS só normaliza lowering,
|
||||||
- e quando precisa criar uma abstração nova de linguagem.
|
- e quando precisa criar uma abstração nova de linguagem.
|
||||||
|
|
||||||
|
Com o contexto atual do packer, a pergunta fica mais precisa:
|
||||||
|
|
||||||
|
- a autoria PBS deve continuar apontando para identificadores “humanos” sem owner operacional claro;
|
||||||
|
- ou deve consumir uma superfície simbólica derivada do snapshot coerente que o packer já mantém para o projeto?
|
||||||
|
|
||||||
|
Se a segunda direção for adotada, o enum sintético de assets não é só ergonomia de editor.
|
||||||
|
Ele passa a ser a projeção tipada, em domínio PBS, de uma autoridade operacional já existente no packer.
|
||||||
|
|
||||||
|
Isso desloca a discussão de “nome versus `asset_id`” para uma formulação melhor:
|
||||||
|
|
||||||
|
- qual é a superfície simbólica correta para o jogo autorar;
|
||||||
|
- quem é owner dessa superfície;
|
||||||
|
- e como essa superfície é lowered para a identidade estável final.
|
||||||
|
|
||||||
|
Também desloca uma segunda discussão para fora do escopo imediato:
|
||||||
|
|
||||||
|
- a agenda atual pode fechar como o jogo referencia o `asset` enquanto unidade instalável/publicável;
|
||||||
|
- mas não deve colapsar isso com o addressing dos internos expostos por `banks`.
|
||||||
|
|
||||||
|
O modelo mais correto parece ser:
|
||||||
|
|
||||||
|
1. o jogo referencia um asset por uma superfície simbólica derivada da autoridade operacional do packer;
|
||||||
|
2. esse asset é instalado/publicado em um `bank` de runtime;
|
||||||
|
3. somente o `bank` passa a expor o espaço de endereçamento de recursos internos;
|
||||||
|
4. esse espaço de endereçamento é específico da família do banco e merece contrato próprio.
|
||||||
|
|
||||||
|
Ao mesmo tempo, a discussão de root references passa a ter três frentes explícitas:
|
||||||
|
|
||||||
|
1. `Studio`
|
||||||
|
- como o asset é exibido e selecionado na UI;
|
||||||
|
- se o address derivado do root substitui o `asset_name` como identidade visível;
|
||||||
|
- como impedir criação/move que faça um path atuar ao mesmo tempo como asset terminal e namespace;
|
||||||
|
2. `packer`
|
||||||
|
- como o snapshot operacional publica o address normatizado;
|
||||||
|
- se `asset.json` deixa de carregar `asset_name` como dado relevante;
|
||||||
|
- como moves/renames impactam o address e a invalidade de referências;
|
||||||
|
3. `compiler/pbs`
|
||||||
|
- como a projeção de assets entra no compile;
|
||||||
|
- como o frontend PBS consome essa projeção sem consultar o packer diretamente;
|
||||||
|
- como o lowering converte `assets.foo.bar` para identidade estável de runtime;
|
||||||
|
- em que ponto da superfície SDK/PBS a ponte `address -> asset_id` realmente acontece.
|
||||||
|
|
||||||
|
No momento, a direção técnica mais forte para essa ponte é:
|
||||||
|
|
||||||
|
- `Addressable` permanece como superfície simbólica de autoria;
|
||||||
|
- `declare host` asset-backed recebe metadata reservada como `[AssetLowering(param = N)]`;
|
||||||
|
- o compiler resolve esse parâmetro durante o lowering da chamada host-backed;
|
||||||
|
- `declare service` público permanece apenas como wrapper ergonômico sobre esse contrato.
|
||||||
|
|
||||||
## Resolution
|
## Resolution
|
||||||
|
|
||||||
Direção recomendada por enquanto:
|
Direção recomendada por enquanto:
|
||||||
|
|
||||||
1. tratar os dois temas como uma única discussão de política de surface-versus-lowering em PBS;
|
1. tratar os dois temas como uma única discussão de política de surface-versus-lowering em PBS;
|
||||||
2. preferir a direção **Option B** como baseline;
|
2. preferir a direção **Option B** como baseline;
|
||||||
3. fechar depois duas decisões derivadas:
|
3. tratar a política de asset references como discussão entre três camadas explícitas:
|
||||||
- política de asset references para código de jogo;
|
- `PackerRuntimeSnapshot` como autoridade operacional do conjunto de assets;
|
||||||
|
- superfície simbólica sintetizada para consumo em PBS;
|
||||||
|
- lowering compiler-owned para identidade estável de runtime;
|
||||||
|
4. explorar explicitamente a remoção de `asset_name` como variável operacional em favor do address derivado do root relativo em `assets/`;
|
||||||
|
5. tratar como requisito arquitetural que a projeção de assets chegue ao frontend PBS pelo backend/orquestração do compile, não por consulta direta do frontend ao packer;
|
||||||
|
6. tratar como questão central da agenda o ponto exato em que a superfície PBS/SDK converte `address` em `asset_id`;
|
||||||
|
7. fechar depois duas decisões derivadas:
|
||||||
|
- política de asset references para código de jogo, agora incluindo owner, forma do address canônico e contrato de entrada BE -> FE da projeção de assets;
|
||||||
- política de descarte de retorno ignorado em `expression statement`;
|
- política de descarte de retorno ignorado em `expression statement`;
|
||||||
4. evitar introduzir nova abstração de linguagem antes de esgotar a via de normalização no compiler.
|
8. registrar explicitamente que addressing de recursos internos instalados em `banks` não pertence ao contrato básico de `asset references` e deve seguir discussão/spec própria, provavelmente em superfície transversal de runtime/banks;
|
||||||
|
9. evitar introduzir nova abstração de linguagem antes de esgotar a via de normalização no compiler e a via de superfície simbólica derivada da autoridade operacional já existente no packer.
|
||||||
|
|
||||||
|
### Current preferred technical shape
|
||||||
|
|
||||||
|
Sem fechar ainda a decision final, a forma técnica hoje preferida nesta agenda é:
|
||||||
|
|
||||||
|
1. `declare host` asset-backed carrega `[AssetLowering(param = ...)]`;
|
||||||
|
2. o parâmetro marcado usa `Addressable` como surface autoral;
|
||||||
|
3. `declare service` público chama normalmente esse host wrapper;
|
||||||
|
4. o compiler resolve `address -> asset_id` ao baixar a chamada host-backed;
|
||||||
|
5. o runtime final continua vendo apenas o contrato operacional por `asset_id`.
|
||||||
|
|
||||||
|
Related shape for the synthetic asset surface:
|
||||||
|
|
||||||
|
1. `assets` is a hierarchical compile-time tree, not a flat enum;
|
||||||
|
2. intermediate nodes are namespaces only;
|
||||||
|
3. terminal asset leaves are typed as `Addressable`;
|
||||||
|
4. compile-time projection currently needs only `address` and `asset_id`;
|
||||||
|
5. Studio/runtime-tooling must reject terminal/namespace path collisions;
|
||||||
|
6. Studio should not allow creating or moving assets in ways that would make the same path act as both terminal asset and namespace prefix.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare host low_assets {
|
||||||
|
[Host(module = "assets", name = "preload", version = 1)]
|
||||||
|
[AssetLowering(param = 0)]
|
||||||
|
fn preload(addressable: Addressable, bank_id: int) -> LoadError;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare service Assets {
|
||||||
|
fn load(addressable: Addressable, bank: BankRef) -> LoadError {
|
||||||
|
return low_assets.preload(addressable, bank.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example:
|
||||||
|
|
||||||
|
- the author-facing API remains `Assets.load(addressable, bank)`;
|
||||||
|
- `low_assets.preload(...)` is the host-backed contract surface;
|
||||||
|
- `[AssetLowering(param = 0)]` tells the compiler that parameter `0` must be resolved from symbolic `Addressable` to operational `asset_id`;
|
||||||
|
- the service body remains ordinary PBS code;
|
||||||
|
- the special behavior lives in reserved lowering metadata on the `declare host` signature.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user