@designliquido/delegua 1.13.2 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/analisador-documentario/index.d.ts +1 -1
  2. package/analisador-semantico/analisador-semantico.d.ts.map +1 -1
  3. package/analisador-semantico/analisador-semantico.js +12 -2
  4. package/analisador-semantico/analisador-semantico.js.map +1 -1
  5. package/avaliador-sintatico/avaliador-sintatico.d.ts.map +1 -1
  6. package/avaliador-sintatico/avaliador-sintatico.js +10 -0
  7. package/avaliador-sintatico/avaliador-sintatico.js.map +1 -1
  8. package/avaliador-sintatico/dialetos/avaliador-sintatico-calango.d.ts +25 -5
  9. package/avaliador-sintatico/dialetos/avaliador-sintatico-calango.d.ts.map +1 -1
  10. package/avaliador-sintatico/dialetos/avaliador-sintatico-calango.js +301 -25
  11. package/avaliador-sintatico/dialetos/avaliador-sintatico-calango.js.map +1 -1
  12. package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.d.ts.map +1 -1
  13. package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js +4 -10
  14. package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js.map +1 -1
  15. package/avaliador-sintatico/dialetos/avaliador-sintatico-tenda.d.ts.map +1 -1
  16. package/avaliador-sintatico/dialetos/avaliador-sintatico-tenda.js +33 -2
  17. package/avaliador-sintatico/dialetos/avaliador-sintatico-tenda.js.map +1 -1
  18. package/bibliotecas/biblioteca-global.d.ts.map +1 -1
  19. package/bibliotecas/biblioteca-global.js +3 -7
  20. package/bibliotecas/biblioteca-global.js.map +1 -1
  21. package/bibliotecas/dialetos/tenda/biblioteca-global.d.ts +3 -0
  22. package/bibliotecas/dialetos/tenda/biblioteca-global.d.ts.map +1 -0
  23. package/bibliotecas/dialetos/tenda/biblioteca-global.js +365 -0
  24. package/bibliotecas/dialetos/tenda/biblioteca-global.js.map +1 -0
  25. package/bin/package.json +1 -1
  26. package/construtos/vetor.d.ts.map +1 -1
  27. package/construtos/vetor.js.map +1 -1
  28. package/interfaces/documentario/documentario-analisado.d.ts +2 -2
  29. package/interfaces/documentario/index.d.ts +3 -3
  30. package/interpretador/depuracao/interpretador-com-depuracao.d.ts.map +1 -1
  31. package/interpretador/depuracao/interpretador-com-depuracao.js +8 -0
  32. package/interpretador/depuracao/interpretador-com-depuracao.js.map +1 -1
  33. package/interpretador/dialetos/calango/interpretador-calango.d.ts +2 -0
  34. package/interpretador/dialetos/calango/interpretador-calango.d.ts.map +1 -1
  35. package/interpretador/dialetos/calango/interpretador-calango.js +15 -0
  36. package/interpretador/dialetos/calango/interpretador-calango.js.map +1 -1
  37. package/interpretador/dialetos/index.d.ts +1 -0
  38. package/interpretador/dialetos/index.d.ts.map +1 -1
  39. package/interpretador/dialetos/index.js +1 -0
  40. package/interpretador/dialetos/index.js.map +1 -1
  41. package/interpretador/dialetos/pitugues/interpretador-pitugues.d.ts.map +1 -1
  42. package/interpretador/dialetos/pitugues/interpretador-pitugues.js.map +1 -1
  43. package/interpretador/dialetos/tenda/index.d.ts +2 -0
  44. package/interpretador/dialetos/tenda/index.d.ts.map +1 -0
  45. package/interpretador/dialetos/tenda/index.js +18 -0
  46. package/interpretador/dialetos/tenda/index.js.map +1 -0
  47. package/interpretador/dialetos/tenda/interpretador-tenda.d.ts +13 -0
  48. package/interpretador/dialetos/tenda/interpretador-tenda.d.ts.map +1 -0
  49. package/interpretador/dialetos/tenda/interpretador-tenda.js +31 -0
  50. package/interpretador/dialetos/tenda/interpretador-tenda.js.map +1 -0
  51. package/interpretador/interpretador.d.ts +2 -1
  52. package/interpretador/interpretador.d.ts.map +1 -1
  53. package/interpretador/interpretador.js +24 -1
  54. package/interpretador/interpretador.js.map +1 -1
  55. package/interpretador/pilha-escopos-execucao.d.ts.map +1 -1
  56. package/interpretador/pilha-escopos-execucao.js +3 -0
  57. package/interpretador/pilha-escopos-execucao.js.map +1 -1
  58. package/lexador/dialetos/lexador-calango.d.ts +1 -0
  59. package/lexador/dialetos/lexador-calango.d.ts.map +1 -1
  60. package/lexador/dialetos/lexador-calango.js +77 -0
  61. package/lexador/dialetos/lexador-calango.js.map +1 -1
  62. package/lexador/dialetos/lexador-pitugues.d.ts.map +1 -1
  63. package/lexador/dialetos/lexador-pitugues.js +2 -4
  64. package/lexador/dialetos/lexador-pitugues.js.map +1 -1
  65. package/lexador/dialetos/palavras-reservadas/calango.d.ts +31 -4
  66. package/lexador/dialetos/palavras-reservadas/calango.d.ts.map +1 -1
  67. package/lexador/dialetos/palavras-reservadas/calango.js +31 -4
  68. package/lexador/dialetos/palavras-reservadas/calango.js.map +1 -1
  69. package/package.json +1 -1
  70. package/tipos-de-simbolos/calango.d.ts +28 -0
  71. package/tipos-de-simbolos/calango.d.ts.map +1 -1
  72. package/tipos-de-simbolos/calango.js +28 -0
  73. package/tipos-de-simbolos/calango.js.map +1 -1
  74. package/tradutores/index.d.ts +2 -0
  75. package/tradutores/index.d.ts.map +1 -1
  76. package/tradutores/index.js +2 -0
  77. package/tradutores/index.js.map +1 -1
  78. package/tradutores/tradutor-assembly-risc-v.d.ts +99 -0
  79. package/tradutores/tradutor-assembly-risc-v.d.ts.map +1 -0
  80. package/tradutores/tradutor-assembly-risc-v.js +685 -0
  81. package/tradutores/tradutor-assembly-risc-v.js.map +1 -0
  82. package/tradutores/tradutor-assemblyscript.js +1 -1
  83. package/tradutores/tradutor-assemblyscript.js.map +1 -1
  84. package/tradutores/tradutor-webassembly.d.ts +159 -0
  85. package/tradutores/tradutor-webassembly.d.ts.map +1 -0
  86. package/tradutores/tradutor-webassembly.js +901 -0
  87. package/tradutores/tradutor-webassembly.js.map +1 -0
  88. package/umd/delegua.js +2066 -279
@@ -0,0 +1,901 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TradutorWebAssembly = void 0;
4
+ const construtos_1 = require("../construtos");
5
+ const declaracoes_1 = require("../declaracoes");
6
+ class TradutorWebAssembly {
7
+ constructor() {
8
+ // ── Seções do módulo WAT ───────────────────────────────────────────────
9
+ /** Segmentos de dados estáticos para strings literais */
10
+ this.segmentosTexto = [];
11
+ /** Próximo byte livre na memória linear para strings */
12
+ this.deslocamentoTexto = 0;
13
+ /** Texto WAT completo de cada função declarada pelo usuário */
14
+ this.funcoesCompletas = [];
15
+ /** Declarações WAT de variáveis globais `(global ...)` */
16
+ this.declaracoesGlobais = [];
17
+ // ── Contexto da função sendo traduzida no momento ──────────────────────
18
+ /** Instruções WAT emitidas no corpo da função corrente */
19
+ this.corpoDaFuncaoAtual = '';
20
+ /** Declarações `(param ...)` e `(local ...)` da função corrente */
21
+ this.declaracoesLocaisAtual = '';
22
+ /** Nomes de locais/params já declarados (evita duplicatas) */
23
+ this.locaisDeclaradosAtual = new Set();
24
+ /** Estamos dentro do corpo de uma função nomeada? */
25
+ this.dentroFuncao = false;
26
+ /** A função corrente possui ao menos um `retorna` com valor? */
27
+ this.funcaoTemRetorno = false;
28
+ // ── Mapa de variáveis ─────────────────────────────────────────────────
29
+ /** Nome Delégua → metadados WAT */
30
+ this.variaveis = new Map();
31
+ // ── Controle de fluxo (break/continue) ───────────────────────────────
32
+ /** Pilha de rótulos de laço para `sustar`/`continua` */
33
+ this.pilhaDeControle = [];
34
+ // ── Geração de rótulos ────────────────────────────────────────────────
35
+ this.contadorRotulos = 0;
36
+ // =========================================================================
37
+ // Dicionário de construtos (expressões)
38
+ // =========================================================================
39
+ this.dicionarioConstrutos = {
40
+ AcessoIndiceVariavel: this.traduzirAcessoIndiceVariavel.bind(this),
41
+ AcessoMetodoOuPropriedade: this.traduzirAcessoMetodo.bind(this),
42
+ Agrupamento: this.traduzirAgrupamento.bind(this),
43
+ AtribuicaoPorIndice: this.traduzirAtribuicaoPorIndice.bind(this),
44
+ Atribuir: this.traduzirAtribuir.bind(this),
45
+ Binario: this.traduzirBinario.bind(this),
46
+ Chamada: this.traduzirChamada.bind(this),
47
+ DefinirValor: this.traduzirDefinirValor.bind(this),
48
+ FuncaoConstruto: this.traduzirFuncaoConstruto.bind(this),
49
+ Literal: this.traduzirLiteral.bind(this),
50
+ Logico: this.traduzirLogico.bind(this),
51
+ TipoDe: this.traduzirTipoDe.bind(this),
52
+ Unario: this.traduzirUnario.bind(this),
53
+ Variavel: this.traduzirVariavel.bind(this),
54
+ Vetor: this.traduzirVetor.bind(this),
55
+ };
56
+ // =========================================================================
57
+ // Dicionário de declarações (instruções)
58
+ // =========================================================================
59
+ this.dicionarioDeclaracoes = {
60
+ Bloco: this.traduzirBloco.bind(this),
61
+ Classe: this.traduzirClasse.bind(this),
62
+ Const: this.traduzirConst.bind(this),
63
+ Continua: this.traduzirContinua.bind(this),
64
+ Enquanto: this.traduzirEnquanto.bind(this),
65
+ Escolha: this.traduzirEscolha.bind(this),
66
+ Escreva: this.traduzirEscreva.bind(this),
67
+ EscrevaMesmaLinha: this.traduzirEscreva.bind(this),
68
+ Expressao: this.traduzirExpressao.bind(this),
69
+ Falhar: this.traduzirFalhar.bind(this),
70
+ Fazer: this.traduzirFazer.bind(this),
71
+ FuncaoDeclaracao: this.traduzirFuncaoDeclaracao.bind(this),
72
+ Importar: this.traduzirImportar.bind(this),
73
+ Para: this.traduzirPara.bind(this),
74
+ ParaCada: this.traduzirParaCada.bind(this),
75
+ Retorna: this.traduzirRetorna.bind(this),
76
+ Se: this.traduzirSe.bind(this),
77
+ Sustar: this.traduzirSustar.bind(this),
78
+ Tente: this.traduzirTente.bind(this),
79
+ Var: this.traduzirVar.bind(this),
80
+ };
81
+ }
82
+ // =========================================================================
83
+ // Helpers internos
84
+ // =========================================================================
85
+ gerarRotulo() {
86
+ return `$L${this.contadorRotulos++}`;
87
+ }
88
+ /** Emite uma instrução indentada no corpo da função corrente. */
89
+ emitir(instrucao) {
90
+ this.corpoDaFuncaoAtual += ` ${instrucao}\n`;
91
+ }
92
+ /**
93
+ * Converte uma string JavaScript para bytes UTF-8.
94
+ * Usa `encodeURIComponent` para extrair os bytes — funciona em qualquer ambiente JS
95
+ * sem depender de APIs específicas de Node.js (Buffer) ou browser (TextEncoder).
96
+ */
97
+ stringParaBytesUtf8(valor) {
98
+ const encoded = encodeURIComponent(valor);
99
+ const bytes = [];
100
+ for (let i = 0; i < encoded.length;) {
101
+ if (encoded[i] === '%') {
102
+ bytes.push(parseInt(encoded.slice(i + 1, i + 3), 16));
103
+ i += 3;
104
+ }
105
+ else {
106
+ bytes.push(encoded.charCodeAt(i));
107
+ i++;
108
+ }
109
+ }
110
+ return bytes;
111
+ }
112
+ /**
113
+ * Converte uma string JavaScript para o formato de literal de string WAT.
114
+ * Bytes não-ASCII e caracteres especiais são hex-escapados como `\xx`.
115
+ * Retorna o literal pronto para uso em `(data ...)` e o comprimento em bytes UTF-8.
116
+ */
117
+ escaparStringWat(valor) {
118
+ const bytes = this.stringParaBytesUtf8(valor);
119
+ let watLiteral = '';
120
+ for (const byte of bytes) {
121
+ if (byte === 0x22) {
122
+ watLiteral += '\\"'; // aspas duplas
123
+ }
124
+ else if (byte === 0x5c) {
125
+ watLiteral += '\\\\'; // contrabarra
126
+ }
127
+ else if (byte >= 0x20 && byte <= 0x7e) {
128
+ watLiteral += String.fromCharCode(byte); // ASCII imprimível
129
+ }
130
+ else {
131
+ watLiteral += `\\${byte.toString(16).padStart(2, '0')}`; // \xx
132
+ }
133
+ }
134
+ return { watLiteral, byteLen: bytes.length };
135
+ }
136
+ /**
137
+ * Internaliza uma string literal na memória linear estática.
138
+ * Strings idênticas são deduplicadas.
139
+ * O comprimento armazenado é o comprimento em bytes UTF-8, não em caracteres.
140
+ */
141
+ internalizarTexto(valor) {
142
+ const existente = this.segmentosTexto.find((s) => s.conteudo === valor);
143
+ if (existente) {
144
+ return { offset: existente.deslocamento, len: existente.tamanho };
145
+ }
146
+ const { byteLen } = this.escaparStringWat(valor);
147
+ const offset = this.deslocamentoTexto;
148
+ this.segmentosTexto.push({ deslocamento: offset, conteudo: valor, tamanho: byteLen });
149
+ this.deslocamentoTexto += byteLen;
150
+ return { offset, len: byteLen };
151
+ }
152
+ /**
153
+ * Infere o tipo WAT de um construto.
154
+ * Strings → i32 (ponteiro). Tudo mais → i64 (padrão, inclusive booleanos).
155
+ */
156
+ inferirTipo(construto) {
157
+ if (construto instanceof construtos_1.Literal && typeof construto.valor === 'string')
158
+ return 'i32';
159
+ return 'i64';
160
+ }
161
+ /**
162
+ * Declara um parâmetro ou variável local para a função corrente.
163
+ * `ehParam = true` emite `(param ...)`, senão `(local ...)`.
164
+ */
165
+ declararParamLocal(nome, tipo, ehParam) {
166
+ if (this.locaisDeclaradosAtual.has(nome))
167
+ return;
168
+ this.locaisDeclaradosAtual.add(nome);
169
+ const watNome = `$${nome}`;
170
+ const diretiva = ehParam ? 'param' : 'local';
171
+ this.declaracoesLocaisAtual += ` (${diretiva} ${watNome} ${tipo})`;
172
+ this.variaveis.set(nome, { watNome, tipo, escopo: 'local' });
173
+ }
174
+ /** Salva o contexto da função corrente e inicializa um novo. */
175
+ salvarEIniciarContextoFuncao() {
176
+ const snapshot = {
177
+ corpoDaFuncaoAtual: this.corpoDaFuncaoAtual,
178
+ declaracoesLocaisAtual: this.declaracoesLocaisAtual,
179
+ locaisDeclaradosAtual: this.locaisDeclaradosAtual,
180
+ dentroFuncao: this.dentroFuncao,
181
+ funcaoTemRetorno: this.funcaoTemRetorno,
182
+ variaveis: new Map(this.variaveis),
183
+ };
184
+ this.corpoDaFuncaoAtual = '';
185
+ this.declaracoesLocaisAtual = '';
186
+ this.locaisDeclaradosAtual = new Set();
187
+ this.dentroFuncao = true;
188
+ this.funcaoTemRetorno = false;
189
+ // Remove locais do mapa — globais permanecem
190
+ for (const [nome, meta] of this.variaveis) {
191
+ if (meta.escopo === 'local')
192
+ this.variaveis.delete(nome);
193
+ }
194
+ return snapshot;
195
+ }
196
+ /** Restaura o contexto de função a partir de um snapshot. */
197
+ restaurarContextoFuncao(snapshot) {
198
+ this.corpoDaFuncaoAtual = snapshot.corpoDaFuncaoAtual;
199
+ this.declaracoesLocaisAtual = snapshot.declaracoesLocaisAtual;
200
+ this.locaisDeclaradosAtual = snapshot.locaisDeclaradosAtual;
201
+ this.dentroFuncao = snapshot.dentroFuncao;
202
+ this.funcaoTemRetorno = snapshot.funcaoTemRetorno;
203
+ this.variaveis = snapshot.variaveis;
204
+ }
205
+ /**
206
+ * Garante que uma variável existe no escopo correto.
207
+ * Retorna o nome WAT da variável (e.g. `$x`).
208
+ */
209
+ garantirVariavel(nome, tipo = 'i64') {
210
+ if (this.variaveis.has(nome)) {
211
+ return this.variaveis.get(nome).watNome;
212
+ }
213
+ if (this.dentroFuncao) {
214
+ this.declararParamLocal(nome, tipo, false);
215
+ return `$${nome}`;
216
+ }
217
+ // Global
218
+ const watNome = `$${nome}`;
219
+ this.declaracoesGlobais.push(` (global ${watNome} (mut ${tipo}) (${tipo}.const 0))`);
220
+ this.variaveis.set(nome, { watNome, tipo, escopo: 'global' });
221
+ return watNome;
222
+ }
223
+ // =========================================================================
224
+ // Dispatch helpers
225
+ // =========================================================================
226
+ traduzirConstruto(construto) {
227
+ const handler = this.dicionarioConstrutos[construto.constructor.name];
228
+ if (handler)
229
+ return handler(construto);
230
+ return `(i64.const 0) ;; construto não suportado: ${construto.constructor.name}`;
231
+ }
232
+ traduzirDeclaracaoInterna(declaracao) {
233
+ const handler = this.dicionarioDeclaracoes[declaracao.constructor.name];
234
+ if (handler)
235
+ handler(declaracao);
236
+ else
237
+ this.emitir(`;; declaração não suportada: ${declaracao.constructor.name}`);
238
+ }
239
+ // =========================================================================
240
+ // Construtos
241
+ // =========================================================================
242
+ traduzirLiteral(construto) {
243
+ if (typeof construto.valor === 'boolean') {
244
+ return `(i64.const ${construto.valor ? 1 : 0})`;
245
+ }
246
+ if (typeof construto.valor === 'string') {
247
+ // Retorna apenas o ponteiro; `escreva` usa internalizarTexto diretamente
248
+ // para obter o comprimento também.
249
+ const { offset } = this.internalizarTexto(construto.valor);
250
+ return `(i32.const ${offset})`;
251
+ }
252
+ if (typeof construto.valor === 'bigint') {
253
+ return `(i64.const ${construto.valor})`;
254
+ }
255
+ // Número: trunca para i64
256
+ return `(i64.const ${Math.trunc(Number(construto.valor))})`;
257
+ }
258
+ traduzirVariavel(construto) {
259
+ var _a;
260
+ const nome = (_a = construto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
261
+ if (!nome)
262
+ return '(i64.const 0)';
263
+ const meta = this.variaveis.get(nome);
264
+ if (!meta)
265
+ return `(i64.const 0) ;; variável desconhecida: ${nome}`;
266
+ const instrucao = meta.escopo === 'local' ? 'local.get' : 'global.get';
267
+ return `(${instrucao} ${meta.watNome})`;
268
+ }
269
+ traduzirAtribuir(construto) {
270
+ var _a;
271
+ let nome;
272
+ if (construto.alvo instanceof construtos_1.Variavel) {
273
+ nome = (_a = construto.alvo.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
274
+ }
275
+ if (!nome)
276
+ return '(i64.const 0)';
277
+ const tipoInferido = this.inferirTipo(construto.valor);
278
+ const watNome = this.garantirVariavel(nome, tipoInferido);
279
+ const valor = this.traduzirConstruto(construto.valor);
280
+ const meta = this.variaveis.get(nome);
281
+ const instrucao = meta.escopo === 'local' ? 'local.set' : 'global.set';
282
+ return `(${instrucao} ${watNome} ${valor})`;
283
+ }
284
+ traduzirBinario(construto) {
285
+ const esq = this.traduzirConstruto(construto.esquerda);
286
+ const dir = this.traduzirConstruto(construto.direita);
287
+ const op = construto.operador.lexema;
288
+ switch (op) {
289
+ case '+':
290
+ return `(i64.add ${esq} ${dir})`;
291
+ case '-':
292
+ return `(i64.sub ${esq} ${dir})`;
293
+ case '*':
294
+ return `(i64.mul ${esq} ${dir})`;
295
+ case '/':
296
+ return `(i64.div_s ${esq} ${dir})`;
297
+ case '%':
298
+ return `(i64.rem_s ${esq} ${dir})`;
299
+ case '<':
300
+ return `(i64.extend_i32_s (i64.lt_s ${esq} ${dir}))`;
301
+ case '>':
302
+ return `(i64.extend_i32_s (i64.gt_s ${esq} ${dir}))`;
303
+ case '<=':
304
+ return `(i64.extend_i32_s (i64.le_s ${esq} ${dir}))`;
305
+ case '>=':
306
+ return `(i64.extend_i32_s (i64.ge_s ${esq} ${dir}))`;
307
+ case '==':
308
+ case '===':
309
+ return `(i64.extend_i32_s (i64.eq ${esq} ${dir}))`;
310
+ case '!=':
311
+ case '!==':
312
+ return `(i64.extend_i32_s (i64.ne ${esq} ${dir}))`;
313
+ default:
314
+ return `(i64.const 0) ;; operador não suportado: ${op}`;
315
+ }
316
+ }
317
+ traduzirLogico(construto) {
318
+ const esq = this.traduzirConstruto(construto.esquerda);
319
+ const dir = this.traduzirConstruto(construto.direita);
320
+ const op = construto.operador.lexema;
321
+ // Ambos os lados avaliados (sem curto-circuito na v1).
322
+ // Converte i64 → i32 (ne 0), aplica i32.and / i32.or, estende de volta.
323
+ const esqBool = `(i32.ne (i32.const 0) (i32.wrap_i64 ${esq}))`;
324
+ const dirBool = `(i32.ne (i32.const 0) (i32.wrap_i64 ${dir}))`;
325
+ if (op === 'e' || op === '&&') {
326
+ return `(i64.extend_i32_s (i32.and ${esqBool} ${dirBool}))`;
327
+ }
328
+ if (op === 'ou' || op === '||') {
329
+ return `(i64.extend_i32_s (i32.or ${esqBool} ${dirBool}))`;
330
+ }
331
+ return `(i64.const 0) ;; operador lógico não suportado: ${op}`;
332
+ }
333
+ traduzirUnario(construto) {
334
+ var _a;
335
+ const op = construto.operador.lexema;
336
+ const operando = this.traduzirConstruto(construto.operando);
337
+ if (op === '-') {
338
+ return `(i64.sub (i64.const 0) ${operando})`;
339
+ }
340
+ if (op === '!' || op === 'nao') {
341
+ return `(i64.extend_i32_s (i64.eqz ${operando}))`;
342
+ }
343
+ if (op === '++' || op === '--') {
344
+ // Apenas pré-incremento/decremento de variável simples na v1
345
+ let nome;
346
+ if (construto.operando instanceof construtos_1.Variavel) {
347
+ nome = (_a = construto.operando.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
348
+ }
349
+ if (!nome)
350
+ return operando;
351
+ const meta = this.variaveis.get(nome);
352
+ if (!meta)
353
+ return operando;
354
+ const instrSet = meta.escopo === 'local' ? 'local.set' : 'global.set';
355
+ const instrGet = meta.escopo === 'local' ? 'local.get' : 'global.get';
356
+ const delta = op === '++' ? 1 : -1;
357
+ const novoValor = `(i64.add ${operando} (i64.const ${delta}))`;
358
+ // Retorna uma sequência: set + get (usando local.tee para locais, ou set;get para globais)
359
+ if (meta.escopo === 'local') {
360
+ return `(local.tee ${meta.watNome} ${novoValor})`;
361
+ }
362
+ // Para globais não existe tee; emitimos o set e retornamos o get
363
+ this.emitir(`(${instrSet} ${meta.watNome} ${novoValor})`);
364
+ return `(${instrGet} ${meta.watNome})`;
365
+ }
366
+ return operando;
367
+ }
368
+ traduzirAgrupamento(construto) {
369
+ return this.traduzirConstruto(construto.expressao);
370
+ }
371
+ traduzirChamada(construto) {
372
+ var _a;
373
+ let nomeFuncao = 'desconhecida';
374
+ if (construto.entidadeChamada instanceof construtos_1.Variavel) {
375
+ nomeFuncao = ((_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'desconhecida';
376
+ }
377
+ const args = construto.argumentos
378
+ .map((arg) => this.traduzirConstruto(arg))
379
+ .join(' ');
380
+ return `(call $${nomeFuncao}${args ? ' ' + args : ''})`;
381
+ }
382
+ traduzirAcessoIndiceVariavel(construto) {
383
+ var _a;
384
+ let baseExpr = '(i32.const 0)';
385
+ if (construto.entidadeChamada instanceof construtos_1.Variavel) {
386
+ const nome = (_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
387
+ const meta = nome ? this.variaveis.get(nome) : undefined;
388
+ if (meta) {
389
+ const instrGet = meta.escopo === 'local' ? 'local.get' : 'global.get';
390
+ baseExpr = `(${instrGet} ${meta.watNome})`;
391
+ }
392
+ }
393
+ const indice = this.traduzirConstruto(construto.indice);
394
+ // base + indice * 8 (cada elemento i64 ocupa 8 bytes)
395
+ const offset = `(i32.add ${baseExpr} (i32.wrap_i64 (i64.mul ${indice} (i64.const 8))))`;
396
+ return `(i64.load ${offset})`;
397
+ }
398
+ traduzirAtribuicaoPorIndice(construto) {
399
+ var _a;
400
+ let baseExpr = '(i32.const 0)';
401
+ if (construto.objeto instanceof construtos_1.Variavel) {
402
+ const nome = (_a = construto.objeto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
403
+ const meta = nome ? this.variaveis.get(nome) : undefined;
404
+ if (meta) {
405
+ const instrGet = meta.escopo === 'local' ? 'local.get' : 'global.get';
406
+ baseExpr = `(${instrGet} ${meta.watNome})`;
407
+ }
408
+ }
409
+ const indice = this.traduzirConstruto(construto.indice);
410
+ const valor = this.traduzirConstruto(construto.valor);
411
+ const offset = `(i32.add ${baseExpr} (i32.wrap_i64 (i64.mul ${indice} (i64.const 8))))`;
412
+ return `(i64.store ${offset} ${valor})`;
413
+ }
414
+ traduzirVetor(construto) {
415
+ var _a, _b;
416
+ // Aloca espaço na memória linear para N × 8 bytes.
417
+ // Os valores são emitidos como instruções de store na função corrente.
418
+ const n = (_b = (_a = construto.valores) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
419
+ const offset = this.deslocamentoTexto;
420
+ // Reserva n * 8 bytes (sem conteúdo estático; preenchido em tempo de execução)
421
+ this.deslocamentoTexto += n * 8;
422
+ if (construto.valores) {
423
+ for (let i = 0; i < n; i++) {
424
+ const valor = this.traduzirConstruto(construto.valores[i]);
425
+ const enderecoElem = `(i32.const ${offset + i * 8})`;
426
+ this.emitir(`(i64.store ${enderecoElem} ${valor})`);
427
+ }
428
+ }
429
+ return `(i32.const ${offset})`;
430
+ }
431
+ traduzirDefinirValor(construto) {
432
+ // Acesso a propriedade de objeto — simplificado na v1
433
+ const valor = this.traduzirConstruto(construto.valor);
434
+ return `${valor} ;; definir valor não totalmente suportado na v1`;
435
+ }
436
+ traduzirFuncaoConstruto(construto) {
437
+ var _a;
438
+ // Função anônima: emite como função nomeada com rótulo gerado
439
+ const rotulo = `__anonima_${this.contadorRotulos++}`;
440
+ const snapshot = this.salvarEIniciarContextoFuncao();
441
+ for (const decl of (_a = construto.corpo) !== null && _a !== void 0 ? _a : []) {
442
+ this.traduzirDeclaracaoInterna(decl);
443
+ }
444
+ this.emitir('(i64.const 0)');
445
+ const funcWat = ` (func $${rotulo}${this.declaracoesLocaisAtual} (result i64)\n` +
446
+ this.corpoDaFuncaoAtual +
447
+ ` )`;
448
+ this.funcoesCompletas.push(funcWat);
449
+ this.restaurarContextoFuncao(snapshot);
450
+ return `(i32.const 0) ;; referência à função anônima $${rotulo}`;
451
+ }
452
+ traduzirAcessoMetodo(_construto) {
453
+ return '(i64.const 0) ;; acesso a método não suportado na v1';
454
+ }
455
+ traduzirTipoDe(construto) {
456
+ return this.traduzirConstruto(construto.valor);
457
+ }
458
+ // =========================================================================
459
+ // Declarações
460
+ // =========================================================================
461
+ traduzirVar(declaracao) {
462
+ var _a;
463
+ const nome = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
464
+ if (!nome)
465
+ return;
466
+ if (declaracao.inicializador instanceof construtos_1.Vetor) {
467
+ // Vetor: aloca em memória e guarda o ponteiro i32 na variável
468
+ if (this.dentroFuncao) {
469
+ this.declararParamLocal(nome, 'i32', false);
470
+ }
471
+ else {
472
+ this.declaracoesGlobais.push(` (global $${nome} (mut i32) (i32.const 0))`);
473
+ this.variaveis.set(nome, { watNome: `$${nome}`, tipo: 'i32', escopo: 'global' });
474
+ }
475
+ const ponteiro = this.traduzirVetor(declaracao.inicializador);
476
+ const meta = this.variaveis.get(nome);
477
+ const instrSet = meta.escopo === 'local' ? 'local.set' : 'global.set';
478
+ this.emitir(`(${instrSet} $${nome} ${ponteiro})`);
479
+ return;
480
+ }
481
+ const tipo = declaracao.inicializador ? this.inferirTipo(declaracao.inicializador) : 'i64';
482
+ if (this.dentroFuncao) {
483
+ this.declararParamLocal(nome, tipo, false);
484
+ if (declaracao.inicializador) {
485
+ const valor = this.traduzirConstruto(declaracao.inicializador);
486
+ this.emitir(`(local.set $${nome} ${valor})`);
487
+ }
488
+ }
489
+ else {
490
+ // Globais WAT só aceitam const-exprs como inicializadores.
491
+ // Literais → inicializador imediato; expressões complexas → init 0 + global.set em $principal.
492
+ if (declaracao.inicializador instanceof construtos_1.Literal) {
493
+ const init = this.traduzirGlobalInit(declaracao.inicializador, tipo);
494
+ this.declaracoesGlobais.push(` (global $${nome} (mut ${tipo}) ${init})`);
495
+ this.variaveis.set(nome, { watNome: `$${nome}`, tipo, escopo: 'global' });
496
+ }
497
+ else {
498
+ this.declaracoesGlobais.push(` (global $${nome} (mut ${tipo}) (${tipo}.const 0))`);
499
+ this.variaveis.set(nome, { watNome: `$${nome}`, tipo, escopo: 'global' });
500
+ if (declaracao.inicializador) {
501
+ const valor = this.traduzirConstruto(declaracao.inicializador);
502
+ this.emitir(`(global.set $${nome} ${valor})`);
503
+ }
504
+ }
505
+ }
506
+ }
507
+ traduzirConst(declaracao) {
508
+ var _a;
509
+ const nome = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
510
+ if (!nome)
511
+ return;
512
+ const tipo = this.inferirTipo(declaracao.inicializador);
513
+ if (this.dentroFuncao) {
514
+ // Dentro de função: trata como local (sem imutabilidade real em WAT)
515
+ this.declararParamLocal(nome, tipo, false);
516
+ const valor = this.traduzirConstruto(declaracao.inicializador);
517
+ this.emitir(`(local.set $${nome} ${valor})`);
518
+ }
519
+ else {
520
+ // Constante global: sem `mut`; apenas literais são válidos como init
521
+ if (declaracao.inicializador instanceof construtos_1.Literal) {
522
+ const init = this.traduzirGlobalInit(declaracao.inicializador, tipo);
523
+ this.declaracoesGlobais.push(` (global $${nome} ${tipo} ${init})`);
524
+ }
525
+ else {
526
+ // Expressão complexa: global imutável não pode ser sobrescrita em WAT.
527
+ // Tratamos como mutável para permitir inicialização tardia.
528
+ this.declaracoesGlobais.push(` (global $${nome} (mut ${tipo}) (${tipo}.const 0))`);
529
+ const valor = this.traduzirConstruto(declaracao.inicializador);
530
+ this.emitir(`(global.set $${nome} ${valor})`);
531
+ }
532
+ this.variaveis.set(nome, { watNome: `$${nome}`, tipo, escopo: 'global' });
533
+ }
534
+ }
535
+ /**
536
+ * Traduz um literal para um WAT const-expr válido como inicializador de global.
537
+ * Apenas literais são aceitos como inicializadores de globais em WAT.
538
+ */
539
+ traduzirGlobalInit(construto, tipo) {
540
+ if (typeof construto.valor === 'boolean')
541
+ return `(i64.const ${construto.valor ? 1 : 0})`;
542
+ if (typeof construto.valor === 'string') {
543
+ const { offset } = this.internalizarTexto(construto.valor);
544
+ return `(i32.const ${offset})`;
545
+ }
546
+ if (typeof construto.valor === 'bigint')
547
+ return `(i64.const ${construto.valor})`;
548
+ return `(${tipo}.const ${Math.trunc(Number(construto.valor))})`;
549
+ }
550
+ traduzirSe(declaracao) {
551
+ const condicao = this.traduzirConstruto(declaracao.condicao);
552
+ this.emitir(`(if`);
553
+ this.emitir(` (i32.wrap_i64 ${condicao})`);
554
+ this.emitir(` (then`);
555
+ if (this.dicionarioDeclaracoes[declaracao.caminhoEntao.constructor.name]) {
556
+ const corpoPrevio = this.corpoDaFuncaoAtual;
557
+ this.corpoDaFuncaoAtual = '';
558
+ this.traduzirDeclaracaoInterna(declaracao.caminhoEntao);
559
+ const corpoEntao = this.corpoDaFuncaoAtual
560
+ .split('\n')
561
+ .map((l) => ` ${l}`)
562
+ .join('\n');
563
+ this.corpoDaFuncaoAtual = corpoPrevio + corpoEntao;
564
+ }
565
+ this.emitir(` )`);
566
+ if (declaracao.caminhoSenao) {
567
+ this.emitir(` (else`);
568
+ const corpoPrevio = this.corpoDaFuncaoAtual;
569
+ this.corpoDaFuncaoAtual = '';
570
+ this.traduzirDeclaracaoInterna(declaracao.caminhoSenao);
571
+ const corpoSenao = this.corpoDaFuncaoAtual
572
+ .split('\n')
573
+ .map((l) => ` ${l}`)
574
+ .join('\n');
575
+ this.corpoDaFuncaoAtual = corpoPrevio + corpoSenao;
576
+ this.emitir(` )`);
577
+ }
578
+ this.emitir(`)`);
579
+ }
580
+ traduzirEnquanto(declaracao) {
581
+ const labelSaida = this.gerarRotulo();
582
+ const labelLaco = this.gerarRotulo();
583
+ this.pilhaDeControle.push({ labelSaida, labelLaco });
584
+ const condicao = this.traduzirConstruto(declaracao.condicao);
585
+ this.emitir(`(block ${labelSaida}`);
586
+ this.emitir(` (loop ${labelLaco}`);
587
+ this.emitir(` (br_if ${labelSaida}`);
588
+ this.emitir(` (i32.eqz (i32.wrap_i64 ${condicao}))`);
589
+ this.emitir(` )`);
590
+ this.traduzirDeclaracaoInterna(declaracao.corpo);
591
+ this.emitir(` (br ${labelLaco})`);
592
+ this.emitir(` )`);
593
+ this.emitir(`)`);
594
+ this.pilhaDeControle.pop();
595
+ }
596
+ traduzirPara(declaracao) {
597
+ // Inicializador
598
+ if (declaracao.inicializador) {
599
+ if (Array.isArray(declaracao.inicializador)) {
600
+ for (const decl of declaracao.inicializador) {
601
+ this.traduzirDeclaracaoInterna(decl);
602
+ }
603
+ }
604
+ else {
605
+ this.traduzirDeclaracaoInterna(declaracao.inicializador);
606
+ }
607
+ }
608
+ const labelSaida = this.gerarRotulo();
609
+ const labelLaco = this.gerarRotulo();
610
+ this.pilhaDeControle.push({ labelSaida, labelLaco });
611
+ const condicao = declaracao.condicao
612
+ ? this.traduzirConstruto(declaracao.condicao)
613
+ : '(i64.const 1)';
614
+ this.emitir(`(block ${labelSaida}`);
615
+ this.emitir(` (loop ${labelLaco}`);
616
+ this.emitir(` (br_if ${labelSaida}`);
617
+ this.emitir(` (i32.eqz (i32.wrap_i64 ${condicao}))`);
618
+ this.emitir(` )`);
619
+ if (declaracao.corpo) {
620
+ this.traduzirDeclaracaoInterna(declaracao.corpo);
621
+ }
622
+ if (declaracao.incrementar) {
623
+ const inc = this.traduzirConstruto(declaracao.incrementar);
624
+ this.emitir(`(drop ${inc})`);
625
+ }
626
+ this.emitir(` (br ${labelLaco})`);
627
+ this.emitir(` )`);
628
+ this.emitir(`)`);
629
+ this.pilhaDeControle.pop();
630
+ }
631
+ traduzirFazer(declaracao) {
632
+ var _a;
633
+ const labelSaida = this.gerarRotulo();
634
+ const labelLaco = this.gerarRotulo();
635
+ this.pilhaDeControle.push({ labelSaida, labelLaco });
636
+ this.emitir(`(block ${labelSaida}`);
637
+ this.emitir(` (loop ${labelLaco}`);
638
+ if ((_a = declaracao.caminhoFazer) === null || _a === void 0 ? void 0 : _a.declaracoes) {
639
+ for (const decl of declaracao.caminhoFazer.declaracoes) {
640
+ this.traduzirDeclaracaoInterna(decl);
641
+ }
642
+ }
643
+ if (declaracao.condicaoEnquanto) {
644
+ const condicao = this.traduzirConstruto(declaracao.condicaoEnquanto);
645
+ // Repete se a condição for verdadeira
646
+ this.emitir(` (br_if ${labelLaco}`);
647
+ this.emitir(` (i32.wrap_i64 ${condicao})`);
648
+ this.emitir(` )`);
649
+ }
650
+ this.emitir(` )`);
651
+ this.emitir(`)`);
652
+ this.pilhaDeControle.pop();
653
+ }
654
+ traduzirEscolha(declaracao) {
655
+ const rotuloEscolha = `__escolha_${this.contadorRotulos++}`;
656
+ const tipo = 'i64';
657
+ // Declara local temporário para o valor do escolha
658
+ this.declararParamLocal(rotuloEscolha, tipo, false);
659
+ const sujeito = this.traduzirConstruto(declaracao.identificadorOuLiteral);
660
+ this.emitir(`(local.set $${rotuloEscolha} ${sujeito})`);
661
+ // Gera cadeia de if/else aninhados
662
+ this.emitirCadeiaEscolha(rotuloEscolha, declaracao.caminhos, declaracao.caminhoPadrao);
663
+ }
664
+ emitirCadeiaEscolha(rotuloEscolha, caminhos, caminhoPadrao, indice = 0) {
665
+ var _a, _b;
666
+ if (indice >= caminhos.length) {
667
+ // Emite o caminho padrão (senao) se existir
668
+ if (caminhoPadrao) {
669
+ for (const decl of (_a = caminhoPadrao.declaracoes) !== null && _a !== void 0 ? _a : []) {
670
+ this.traduzirDeclaracaoInterna(decl);
671
+ }
672
+ }
673
+ return;
674
+ }
675
+ const caminho = caminhos[indice];
676
+ if (!caminho.condicoes || caminho.condicoes.length === 0) {
677
+ this.emitirCadeiaEscolha(rotuloEscolha, caminhos, caminhoPadrao, indice + 1);
678
+ return;
679
+ }
680
+ // Condição: qualquer das condicoes casa com o valor do escolha
681
+ const primeiraCond = `(i64.eq (local.get $${rotuloEscolha}) ${this.traduzirConstruto(caminho.condicoes[0])})`;
682
+ let condicaoFinal = primeiraCond;
683
+ for (let i = 1; i < caminho.condicoes.length; i++) {
684
+ const outraCond = `(i64.eq (local.get $${rotuloEscolha}) ${this.traduzirConstruto(caminho.condicoes[i])})`;
685
+ condicaoFinal = `(i32.or ${condicaoFinal} ${outraCond})`;
686
+ }
687
+ this.emitir(`(if`);
688
+ this.emitir(` ${condicaoFinal}`);
689
+ this.emitir(` (then`);
690
+ for (const decl of (_b = caminho.declaracoes) !== null && _b !== void 0 ? _b : []) {
691
+ this.traduzirDeclaracaoInterna(decl);
692
+ }
693
+ this.emitir(` )`);
694
+ const temProximo = indice + 1 < caminhos.length || caminhoPadrao != null;
695
+ if (temProximo) {
696
+ this.emitir(` (else`);
697
+ this.emitirCadeiaEscolha(rotuloEscolha, caminhos, caminhoPadrao, indice + 1);
698
+ this.emitir(` )`);
699
+ }
700
+ this.emitir(`)`);
701
+ }
702
+ traduzirBloco(declaracao) {
703
+ var _a;
704
+ for (const decl of (_a = declaracao.declaracoes) !== null && _a !== void 0 ? _a : []) {
705
+ this.traduzirDeclaracaoInterna(decl);
706
+ }
707
+ }
708
+ traduzirExpressao(declaracao) {
709
+ if (!declaracao.expressao)
710
+ return;
711
+ const expr = this.traduzirConstruto(declaracao.expressao);
712
+ // Atribuições e stores não deixam valor na pilha; outros sim → drop
713
+ const deixaValor = !(declaracao.expressao instanceof construtos_1.Atribuir) &&
714
+ !(declaracao.expressao instanceof construtos_1.AtribuicaoPorIndice);
715
+ if (deixaValor) {
716
+ this.emitir(`(drop ${expr})`);
717
+ }
718
+ else {
719
+ this.emitir(expr);
720
+ }
721
+ }
722
+ traduzirEscreva(declaracao) {
723
+ for (const arg of declaracao.argumentos) {
724
+ if (arg instanceof construtos_1.Literal && typeof arg.valor === 'string') {
725
+ const { offset, len } = this.internalizarTexto(arg.valor);
726
+ this.emitir(`(call $__escreva_texto (i32.const ${offset}) (i32.const ${len}))`);
727
+ }
728
+ else {
729
+ const expr = this.traduzirConstruto(arg);
730
+ this.emitir(`(call $__escreva_inteiro ${expr})`);
731
+ }
732
+ }
733
+ }
734
+ traduzirRetorna(declaracao) {
735
+ this.funcaoTemRetorno = true;
736
+ if (declaracao.valor) {
737
+ const valor = this.traduzirConstruto(declaracao.valor);
738
+ this.emitir(`(return ${valor})`);
739
+ }
740
+ else {
741
+ this.emitir(`(return (i64.const 0))`);
742
+ }
743
+ }
744
+ traduzirSustar(_declaracao) {
745
+ const topo = this.pilhaDeControle[this.pilhaDeControle.length - 1];
746
+ if (topo) {
747
+ this.emitir(`(br ${topo.labelSaida})`);
748
+ }
749
+ }
750
+ traduzirContinua(_declaracao) {
751
+ const topo = this.pilhaDeControle[this.pilhaDeControle.length - 1];
752
+ if (topo) {
753
+ this.emitir(`(br ${topo.labelLaco})`);
754
+ }
755
+ }
756
+ traduzirFuncaoDeclaracao(declaracao) {
757
+ var _a, _b, _c, _d, _e, _f;
758
+ const nome = (_b = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) !== null && _b !== void 0 ? _b : `__func_${this.contadorRotulos++}`;
759
+ const snapshot = this.salvarEIniciarContextoFuncao();
760
+ // Declara parâmetros
761
+ for (const param of (_d = (_c = declaracao.funcao) === null || _c === void 0 ? void 0 : _c.parametros) !== null && _d !== void 0 ? _d : []) {
762
+ this.declararParamLocal(param.nome.lexema, 'i64', true);
763
+ }
764
+ // Traduz corpo
765
+ for (const decl of (_f = (_e = declaracao.funcao) === null || _e === void 0 ? void 0 : _e.corpo) !== null && _f !== void 0 ? _f : []) {
766
+ this.traduzirDeclaracaoInterna(decl);
767
+ }
768
+ // Retorno implícito 0 (garante stack completo)
769
+ this.emitir('(i64.const 0)');
770
+ const ehPrincipal = nome === 'principal';
771
+ const exportar = ehPrincipal ? ' (export "principal")' : '';
772
+ const funcWat = ` (func $${nome}${exportar}${this.declaracoesLocaisAtual} (result i64)\n` +
773
+ this.corpoDaFuncaoAtual +
774
+ ` )`;
775
+ this.funcoesCompletas.push(funcWat);
776
+ this.restaurarContextoFuncao(snapshot);
777
+ }
778
+ traduzirFalhar(declaracao) {
779
+ // `unreachable` = trap incondicional em WebAssembly
780
+ let msg = '';
781
+ if (declaracao.explicacao) {
782
+ try {
783
+ msg = ` ;; ${this.traduzirConstruto(declaracao.explicacao)}`;
784
+ }
785
+ catch (_a) {
786
+ // ignore
787
+ }
788
+ }
789
+ this.emitir(`(unreachable)${msg}`);
790
+ }
791
+ traduzirImportar(_declaracao) {
792
+ this.emitir(`;; importar não suportado em WebAssembly nativo`);
793
+ }
794
+ traduzirTente(declaracao) {
795
+ var _a;
796
+ this.emitir(`;; tente/pegue: tratamento de exceções é v2`);
797
+ for (const decl of (_a = declaracao.caminhoTente) !== null && _a !== void 0 ? _a : []) {
798
+ this.traduzirDeclaracaoInterna(decl);
799
+ }
800
+ }
801
+ traduzirClasse(_declaracao) {
802
+ this.emitir(`;; classe: não suportada na v1`);
803
+ }
804
+ traduzirParaCada(declaracao) {
805
+ this.emitir(`;; para cada: requer suporte a iteráveis (v2)`);
806
+ if (declaracao.corpo) {
807
+ this.traduzirDeclaracaoInterna(declaracao.corpo);
808
+ }
809
+ }
810
+ // =========================================================================
811
+ // Método principal
812
+ // =========================================================================
813
+ /**
814
+ * Traduz uma lista de declarações Delégua para um módulo WAT.
815
+ * Retorna a string completa do módulo.
816
+ */
817
+ traduzir(declaracoes) {
818
+ // Verifica se o usuário declarou explicitamente `funcao principal()`
819
+ const principalDeclarado = declaracoes.some((d) => { var _a; return d instanceof declaracoes_1.FuncaoDeclaracao && ((_a = d.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) === 'principal'; });
820
+ // Processa todas as declarações de nível superior
821
+ for (const declaracao of declaracoes) {
822
+ this.traduzirDeclaracaoInterna(declaracao);
823
+ }
824
+ // Se o usuário não declarou principal(), envolve os stmts de topo em $principal
825
+ if (!principalDeclarado) {
826
+ const corpoTopo = this.corpoDaFuncaoAtual;
827
+ const locaisDeclarados = this.declaracoesLocaisAtual;
828
+ const funcPrincipal = ` (func $principal (export "principal")${locaisDeclarados} (result i64)\n` +
829
+ corpoTopo +
830
+ ` (i64.const 0)\n` +
831
+ ` )`;
832
+ this.funcoesCompletas.push(funcPrincipal);
833
+ }
834
+ // ── Monta as seções do módulo ────────────────────────────────────────
835
+ const linhasImports = [
836
+ ` (import "delegua" "escreva_texto" (func $__escreva_texto (param i32 i32)))`,
837
+ ` (import "delegua" "escreva_inteiro" (func $__escreva_inteiro (param i64)))`,
838
+ ];
839
+ const linhaMemoria = ` (memory (export "memory") 1)`;
840
+ const linhasDados = this.segmentosTexto.map((s) => {
841
+ const { watLiteral } = this.escaparStringWat(s.conteudo);
842
+ return ` (data (i32.const ${s.deslocamento}) "${watLiteral}")`;
843
+ });
844
+ const partes = ['(module', ...linhasImports, '', linhaMemoria];
845
+ if (linhasDados.length > 0) {
846
+ partes.push('');
847
+ partes.push(...linhasDados);
848
+ }
849
+ if (this.declaracoesGlobais.length > 0) {
850
+ partes.push('');
851
+ partes.push(...this.declaracoesGlobais);
852
+ }
853
+ if (this.funcoesCompletas.length > 0) {
854
+ partes.push('');
855
+ partes.push(...this.funcoesCompletas);
856
+ }
857
+ partes.push(')');
858
+ return partes.join('\n');
859
+ }
860
+ // =========================================================================
861
+ // Arquivo host JavaScript
862
+ // =========================================================================
863
+ /**
864
+ * Gera um arquivo `.mjs` host para executar o módulo WASM no Node.js.
865
+ * Fornece os imports necessários (`delegua.escreva_texto`, `delegua.escreva_inteiro`).
866
+ */
867
+ gerarArquivoHost() {
868
+ return `// Gerado por Delégua -> WebAssembly
869
+ // Uso: node delegua-host.mjs <arquivo.wasm>
870
+ import { readFileSync } from 'fs';
871
+
872
+ const args = process.argv.slice(2);
873
+ const wasmPath = args[0] ?? 'saida.wasm';
874
+
875
+ let memoryExport;
876
+
877
+ const importObject = {
878
+ delegua: {
879
+ /** Imprime texto a partir de um ponteiro e comprimento na memória linear. */
880
+ escreva_texto(ptr, len) {
881
+ const bytes = new Uint8Array(memoryExport.buffer, ptr, len);
882
+ process.stdout.write(new TextDecoder('utf-8').decode(bytes));
883
+ },
884
+ /** Imprime um inteiro de 64 bits (recebido como BigInt no JS). */
885
+ escreva_inteiro(valor) {
886
+ process.stdout.write(String(valor));
887
+ },
888
+ }
889
+ };
890
+
891
+ const wasmBuffer = readFileSync(wasmPath);
892
+ const { instance } = await WebAssembly.instantiate(wasmBuffer, importObject);
893
+ memoryExport = instance.exports.memory;
894
+
895
+ const codigoSaida = Number(instance.exports.principal());
896
+ process.exit(codigoSaida);
897
+ `;
898
+ }
899
+ }
900
+ exports.TradutorWebAssembly = TradutorWebAssembly;
901
+ //# sourceMappingURL=tradutor-webassembly.js.map