@designliquido/delegua 1.13.2 → 1.14.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.
- package/bin/package.json +1 -1
- package/package.json +1 -1
- package/tradutores/index.d.ts +2 -0
- package/tradutores/index.d.ts.map +1 -1
- package/tradutores/index.js +2 -0
- package/tradutores/index.js.map +1 -1
- package/tradutores/tradutor-assembly-risc-v.d.ts +99 -0
- package/tradutores/tradutor-assembly-risc-v.d.ts.map +1 -0
- package/tradutores/tradutor-assembly-risc-v.js +685 -0
- package/tradutores/tradutor-assembly-risc-v.js.map +1 -0
- package/tradutores/tradutor-assemblyscript.js +1 -1
- package/tradutores/tradutor-assemblyscript.js.map +1 -1
- package/tradutores/tradutor-webassembly.d.ts +159 -0
- package/tradutores/tradutor-webassembly.d.ts.map +1 -0
- package/tradutores/tradutor-webassembly.js +895 -0
- package/tradutores/tradutor-webassembly.js.map +1 -0
- package/umd/delegua.js +1833 -249
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TradutorAssemblyRISCV = void 0;
|
|
4
|
+
const construtos_1 = require("../construtos");
|
|
5
|
+
const declaracoes_1 = require("../declaracoes");
|
|
6
|
+
class TradutorAssemblyRISCV {
|
|
7
|
+
constructor(alvo = 'linux-rv64') {
|
|
8
|
+
this.alvo = alvo;
|
|
9
|
+
this.indentacao = 0;
|
|
10
|
+
this.contadorLabels = 0;
|
|
11
|
+
this.variaveis = new Map();
|
|
12
|
+
// s2-s9 são callee-saved — seguros para usar como scratch entre chamadas
|
|
13
|
+
this.registradoresDisponiveis = ['s2', 's3', 's4', 's5', 's6', 's7', 's8', 's9'];
|
|
14
|
+
this.pilhaRegistradores = [];
|
|
15
|
+
this.bss = '.bss\n';
|
|
16
|
+
this.data = '.data\n';
|
|
17
|
+
this.dicionarioConstrutos = {
|
|
18
|
+
AcessoIndiceVariavel: this.traduzirAcessoIndiceVariavel.bind(this),
|
|
19
|
+
AcessoMetodoOuPropriedade: this.traduzirConstrutoAcessoMetodo.bind(this),
|
|
20
|
+
Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
|
|
21
|
+
AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
|
|
22
|
+
Atribuir: this.traduzirConstrutoAtribuir.bind(this),
|
|
23
|
+
Binario: this.traduzirConstrutoBinario.bind(this),
|
|
24
|
+
Chamada: this.traduzirConstrutoChamada.bind(this),
|
|
25
|
+
DefinirValor: this.traduzirConstrutoDefinirValor.bind(this),
|
|
26
|
+
FuncaoConstruto: this.traduzirFuncaoConstruto.bind(this),
|
|
27
|
+
Isto: () => 'this',
|
|
28
|
+
Literal: this.traduzirConstrutoLiteral.bind(this),
|
|
29
|
+
Logico: this.traduzirConstrutoLogico.bind(this),
|
|
30
|
+
TipoDe: this.traduzirConstrutoTipoDe.bind(this),
|
|
31
|
+
Unario: this.traduzirConstrutoUnario.bind(this),
|
|
32
|
+
Variavel: this.traduzirConstrutoVariavel.bind(this),
|
|
33
|
+
Vetor: this.traduzirConstrutoVetor.bind(this),
|
|
34
|
+
};
|
|
35
|
+
this.dicionarioDeclaracoes = {
|
|
36
|
+
Bloco: this.traduzirDeclaracaoBloco.bind(this),
|
|
37
|
+
Enquanto: this.traduzirDeclaracaoEnquanto.bind(this),
|
|
38
|
+
Continua: () => 'j .continue_label',
|
|
39
|
+
Escolha: this.traduzirDeclaracaoEscolha.bind(this),
|
|
40
|
+
Escreva: this.traduzirDeclaracaoEscreva.bind(this),
|
|
41
|
+
Expressao: this.traduzirDeclaracaoExpressao.bind(this),
|
|
42
|
+
Fazer: this.traduzirDeclaracaoFazer.bind(this),
|
|
43
|
+
Falhar: this.traduzirDeclaracaoFalhar.bind(this),
|
|
44
|
+
FuncaoDeclaracao: this.traduzirDeclaracaoFuncao.bind(this),
|
|
45
|
+
Importar: this.traduzirDeclaracaoImportar.bind(this),
|
|
46
|
+
Leia: this.traduzirDeclaracaoLeia.bind(this),
|
|
47
|
+
Para: this.traduzirDeclaracaoPara.bind(this),
|
|
48
|
+
ParaCada: this.traduzirDeclaracaoParaCada.bind(this),
|
|
49
|
+
Retorna: this.traduzirDeclaracaoRetorna.bind(this),
|
|
50
|
+
Se: this.traduzirDeclaracaoSe.bind(this),
|
|
51
|
+
Sustar: () => 'j .break_label',
|
|
52
|
+
Classe: this.traduzirDeclaracaoClasse.bind(this),
|
|
53
|
+
Tente: this.traduzirDeclaracaoTente.bind(this),
|
|
54
|
+
Const: this.traduzirDeclaracaoConst.bind(this),
|
|
55
|
+
Var: this.traduzirDeclaracaoVar.bind(this),
|
|
56
|
+
};
|
|
57
|
+
this.indentacao = 0;
|
|
58
|
+
this.text = `
|
|
59
|
+
.text
|
|
60
|
+
.global _start
|
|
61
|
+
|
|
62
|
+
_start:`;
|
|
63
|
+
}
|
|
64
|
+
gerarDigitoAleatorio() {
|
|
65
|
+
let result = '';
|
|
66
|
+
const digits = '0123456789';
|
|
67
|
+
for (let i = 0; i < 5; i++) {
|
|
68
|
+
const randomIndex = Math.floor(Math.random() * digits.length);
|
|
69
|
+
result += digits.charAt(randomIndex);
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
gerarLabel() {
|
|
74
|
+
return `.L${this.contadorLabels++}`;
|
|
75
|
+
}
|
|
76
|
+
obterRegistrador() {
|
|
77
|
+
if (this.registradoresDisponiveis.length > 0) {
|
|
78
|
+
const reg = this.registradoresDisponiveis.pop();
|
|
79
|
+
this.pilhaRegistradores.push(reg);
|
|
80
|
+
return reg;
|
|
81
|
+
}
|
|
82
|
+
return 'a0'; // fallback
|
|
83
|
+
}
|
|
84
|
+
liberarRegistrador(reg) {
|
|
85
|
+
const index = this.pilhaRegistradores.indexOf(reg);
|
|
86
|
+
if (index > -1) {
|
|
87
|
+
this.pilhaRegistradores.splice(index, 1);
|
|
88
|
+
this.registradoresDisponiveis.push(reg);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Emite a instrução de carga correta para o registrador destino.
|
|
92
|
+
// RISC-V não tem um `ldr reg, =value` polimórfico como ARM —
|
|
93
|
+
// usa `li` para inteiros e `la` para endereços de símbolos.
|
|
94
|
+
emitirCarga(registrador, valor) {
|
|
95
|
+
if (valor === registrador)
|
|
96
|
+
return;
|
|
97
|
+
if (valor === 'null') {
|
|
98
|
+
this.text += `\n li ${registrador}, 0`;
|
|
99
|
+
}
|
|
100
|
+
else if (/^-?\d+$/.test(valor) || valor === 'true' || valor === 'false') {
|
|
101
|
+
const numVal = valor === 'true' ? '1' : valor === 'false' ? '0' : valor;
|
|
102
|
+
this.text += `\n li ${registrador}, ${numVal}`;
|
|
103
|
+
}
|
|
104
|
+
else if (/^-?\d+\.\d+$/.test(valor)) {
|
|
105
|
+
// Ponto flutuante: armazenar em .data e carregar endereço.
|
|
106
|
+
// Operações FPU não são suportadas por esta implementação básica.
|
|
107
|
+
const floatLabel = `float_${this.gerarDigitoAleatorio()}`;
|
|
108
|
+
this.data += ` ${floatLabel}: .double ${valor}\n`;
|
|
109
|
+
this.text += `\n la ${registrador}, ${floatLabel}`;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.text += `\n la ${registrador}, ${valor}`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Implementação dos Construtos
|
|
116
|
+
traduzirAcessoIndiceVariavel(construto) {
|
|
117
|
+
var _a;
|
|
118
|
+
let nomeVar;
|
|
119
|
+
if (construto.entidadeChamada instanceof construtos_1.Variavel) {
|
|
120
|
+
nomeVar = (_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
121
|
+
}
|
|
122
|
+
if (!nomeVar)
|
|
123
|
+
nomeVar = 'unknown';
|
|
124
|
+
const indice = this.dicionarioConstrutos[construto.indice.constructor.name](construto.indice);
|
|
125
|
+
const reg = this.obterRegistrador();
|
|
126
|
+
this.text += `\n la ${reg}, ${nomeVar}`;
|
|
127
|
+
this.emitirCarga('a0', indice);
|
|
128
|
+
this.text += `
|
|
129
|
+
slli a0, a0, 3 # multiplicar índice por 8 (palavra de 64 bits)
|
|
130
|
+
add ${reg}, ${reg}, a0
|
|
131
|
+
ld a0, 0(${reg})`;
|
|
132
|
+
this.liberarRegistrador(reg);
|
|
133
|
+
return 'a0';
|
|
134
|
+
}
|
|
135
|
+
traduzirConstrutoAcessoMetodo(construto) {
|
|
136
|
+
const objeto = this.dicionarioConstrutos[construto.objeto.constructor.name](construto.objeto);
|
|
137
|
+
return `${objeto}_${construto.nomeMetodo}`;
|
|
138
|
+
}
|
|
139
|
+
traduzirConstrutoAgrupamento(construto) {
|
|
140
|
+
return this.dicionarioConstrutos[construto.expressao.constructor.name](construto.expressao);
|
|
141
|
+
}
|
|
142
|
+
traduzirConstrutoAtribuicaoPorIndice(construto) {
|
|
143
|
+
var _a;
|
|
144
|
+
let nomeVar;
|
|
145
|
+
if (construto.objeto instanceof construtos_1.Variavel) {
|
|
146
|
+
nomeVar = (_a = construto.objeto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
147
|
+
}
|
|
148
|
+
if (!nomeVar)
|
|
149
|
+
nomeVar = 'unknown';
|
|
150
|
+
const indice = this.dicionarioConstrutos[construto.indice.constructor.name](construto.indice);
|
|
151
|
+
const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
|
|
152
|
+
const reg = this.obterRegistrador();
|
|
153
|
+
this.text += `\n la ${reg}, ${nomeVar}`;
|
|
154
|
+
this.emitirCarga('a1', indice);
|
|
155
|
+
this.text += `
|
|
156
|
+
slli a1, a1, 3 # multiplicar índice por 8
|
|
157
|
+
add ${reg}, ${reg}, a1`;
|
|
158
|
+
this.emitirCarga('a1', valor);
|
|
159
|
+
this.text += `\n sd a1, 0(${reg})`;
|
|
160
|
+
this.liberarRegistrador(reg);
|
|
161
|
+
}
|
|
162
|
+
traduzirConstrutoAtribuir(construto) {
|
|
163
|
+
var _a;
|
|
164
|
+
let nomeVar;
|
|
165
|
+
if (construto.alvo instanceof construtos_1.Variavel) {
|
|
166
|
+
nomeVar = (_a = construto.alvo.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
167
|
+
}
|
|
168
|
+
if (!nomeVar)
|
|
169
|
+
return;
|
|
170
|
+
const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
|
|
171
|
+
if (!this.variaveis.has(nomeVar)) {
|
|
172
|
+
const varLabel = `var_${nomeVar}`;
|
|
173
|
+
this.bss += ` ${varLabel}: .space 8\n`;
|
|
174
|
+
this.variaveis.set(nomeVar, varLabel);
|
|
175
|
+
}
|
|
176
|
+
this.emitirCarga('a0', valor);
|
|
177
|
+
this.text += `
|
|
178
|
+
la a1, ${this.variaveis.get(nomeVar)}
|
|
179
|
+
sd a0, 0(a1)`;
|
|
180
|
+
}
|
|
181
|
+
traduzirConstrutoBinario(construto) {
|
|
182
|
+
const esquerda = this.dicionarioConstrutos[construto.esquerda.constructor.name](construto.esquerda);
|
|
183
|
+
const direita = this.dicionarioConstrutos[construto.direita.constructor.name](construto.direita);
|
|
184
|
+
const operador = construto.operador.lexema;
|
|
185
|
+
const reg = this.obterRegistrador();
|
|
186
|
+
// Carregar operando esquerdo em a0
|
|
187
|
+
if (esquerda !== 'a0') {
|
|
188
|
+
this.emitirCarga('a0', esquerda);
|
|
189
|
+
}
|
|
190
|
+
// Carregar operando direito no registrador scratch
|
|
191
|
+
this.emitirCarga(reg, direita);
|
|
192
|
+
switch (operador) {
|
|
193
|
+
case '+':
|
|
194
|
+
this.text += `\n add a0, a0, ${reg}`;
|
|
195
|
+
break;
|
|
196
|
+
case '-':
|
|
197
|
+
this.text += `\n sub a0, a0, ${reg}`;
|
|
198
|
+
break;
|
|
199
|
+
case '*':
|
|
200
|
+
this.text += `\n mul a0, a0, ${reg}`;
|
|
201
|
+
break;
|
|
202
|
+
case '/':
|
|
203
|
+
this.text += `\n div a0, a0, ${reg}`;
|
|
204
|
+
break;
|
|
205
|
+
case '%':
|
|
206
|
+
// `rem` é instrução única na extensão M (universal em rv64 Linux)
|
|
207
|
+
this.text += `\n rem a0, a0, ${reg}`;
|
|
208
|
+
break;
|
|
209
|
+
case '<':
|
|
210
|
+
// slt: a0 = 1 se a0 < reg
|
|
211
|
+
this.text += `\n slt a0, a0, ${reg}`;
|
|
212
|
+
break;
|
|
213
|
+
case '>':
|
|
214
|
+
// slt com operandos trocados: a0 = 1 se reg < a0, i.e., a0 > reg
|
|
215
|
+
this.text += `\n slt a0, ${reg}, a0`;
|
|
216
|
+
break;
|
|
217
|
+
case '<=':
|
|
218
|
+
// NOT(a0 > reg) = NOT(reg < a0)
|
|
219
|
+
this.text += `\n slt a0, ${reg}, a0\n xori a0, a0, 1`;
|
|
220
|
+
break;
|
|
221
|
+
case '>=':
|
|
222
|
+
// NOT(a0 < reg)
|
|
223
|
+
this.text += `\n slt a0, a0, ${reg}\n xori a0, a0, 1`;
|
|
224
|
+
break;
|
|
225
|
+
case '==':
|
|
226
|
+
case '===':
|
|
227
|
+
// sub + seqz: a0 = 1 se a0 - reg == 0
|
|
228
|
+
this.text += `\n sub a0, a0, ${reg}\n seqz a0, a0`;
|
|
229
|
+
break;
|
|
230
|
+
case '!=':
|
|
231
|
+
case '!==':
|
|
232
|
+
// sub + snez: a0 = 1 se a0 - reg != 0
|
|
233
|
+
this.text += `\n sub a0, a0, ${reg}\n snez a0, a0`;
|
|
234
|
+
break;
|
|
235
|
+
default:
|
|
236
|
+
this.text += `\n # Operador ${operador} não implementado`;
|
|
237
|
+
}
|
|
238
|
+
this.liberarRegistrador(reg);
|
|
239
|
+
return 'a0';
|
|
240
|
+
}
|
|
241
|
+
traduzirConstrutoChamada(construto) {
|
|
242
|
+
var _a;
|
|
243
|
+
let nomeFuncao = 'funcao';
|
|
244
|
+
if (construto.entidadeChamada instanceof construtos_1.Variavel) {
|
|
245
|
+
nomeFuncao = ((_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'funcao';
|
|
246
|
+
}
|
|
247
|
+
// Convenção RISC-V: a0-a7 para até 8 argumentos
|
|
248
|
+
const registrosArgs = ['a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7'];
|
|
249
|
+
construto.argumentos.forEach((arg, index) => {
|
|
250
|
+
if (index < registrosArgs.length) {
|
|
251
|
+
const valorArg = this.dicionarioConstrutos[arg.constructor.name](arg);
|
|
252
|
+
if (valorArg !== registrosArgs[index]) {
|
|
253
|
+
this.emitirCarga(registrosArgs[index], valorArg);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
this.text += `\n call ${nomeFuncao}`;
|
|
258
|
+
}
|
|
259
|
+
traduzirConstrutoDefinirValor(construto) {
|
|
260
|
+
const objeto = this.dicionarioConstrutos[construto.objeto.constructor.name](construto.objeto);
|
|
261
|
+
const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
|
|
262
|
+
this.emitirCarga('a0', valor);
|
|
263
|
+
this.text += `
|
|
264
|
+
la a1, ${objeto}
|
|
265
|
+
sd a0, 0(a1)`;
|
|
266
|
+
}
|
|
267
|
+
traduzirFuncaoConstruto(construto) {
|
|
268
|
+
const labelFuncao = `func_${this.gerarDigitoAleatorio()}`;
|
|
269
|
+
this.text += `
|
|
270
|
+
|
|
271
|
+
${labelFuncao}:
|
|
272
|
+
addi sp, sp, -16
|
|
273
|
+
sd ra, 8(sp)
|
|
274
|
+
sd s0, 0(sp)
|
|
275
|
+
addi s0, sp, 16`;
|
|
276
|
+
if (construto.corpo && Array.isArray(construto.corpo)) {
|
|
277
|
+
construto.corpo.forEach((declaracao) => {
|
|
278
|
+
if (this.dicionarioDeclaracoes[declaracao.constructor.name]) {
|
|
279
|
+
this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
this.text += `
|
|
284
|
+
ld ra, 8(sp)
|
|
285
|
+
ld s0, 0(sp)
|
|
286
|
+
addi sp, sp, 16
|
|
287
|
+
ret`;
|
|
288
|
+
}
|
|
289
|
+
traduzirConstrutoLiteral(construto) {
|
|
290
|
+
if (typeof construto.valor === 'string') {
|
|
291
|
+
return this.criaStringLiteral(construto);
|
|
292
|
+
}
|
|
293
|
+
return String(construto.valor);
|
|
294
|
+
}
|
|
295
|
+
traduzirConstrutoLogico(construto) {
|
|
296
|
+
const esquerda = this.dicionarioConstrutos[construto.esquerda.constructor.name](construto.esquerda);
|
|
297
|
+
const direita = this.dicionarioConstrutos[construto.direita.constructor.name](construto.direita);
|
|
298
|
+
const operador = construto.operador.lexema;
|
|
299
|
+
const labelVerdadeiro = this.gerarLabel();
|
|
300
|
+
const labelFim = this.gerarLabel();
|
|
301
|
+
this.emitirCarga('a0', esquerda);
|
|
302
|
+
if (operador === 'e' || operador === '&&') {
|
|
303
|
+
this.text += `\n beqz a0, ${labelFim}`;
|
|
304
|
+
this.emitirCarga('a0', direita);
|
|
305
|
+
this.text += `
|
|
306
|
+
beqz a0, ${labelFim}
|
|
307
|
+
${labelVerdadeiro}:
|
|
308
|
+
li a0, 1
|
|
309
|
+
${labelFim}:`;
|
|
310
|
+
}
|
|
311
|
+
else if (operador === 'ou' || operador === '||') {
|
|
312
|
+
this.text += `\n bnez a0, ${labelVerdadeiro}`;
|
|
313
|
+
this.emitirCarga('a0', direita);
|
|
314
|
+
this.text += `
|
|
315
|
+
bnez a0, ${labelVerdadeiro}
|
|
316
|
+
li a0, 0
|
|
317
|
+
j ${labelFim}
|
|
318
|
+
${labelVerdadeiro}:
|
|
319
|
+
li a0, 1
|
|
320
|
+
${labelFim}:`;
|
|
321
|
+
}
|
|
322
|
+
return 'a0';
|
|
323
|
+
}
|
|
324
|
+
traduzirConstrutoTipoDe(construto) {
|
|
325
|
+
return this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
|
|
326
|
+
}
|
|
327
|
+
traduzirConstrutoUnario(construto) {
|
|
328
|
+
const operando = this.dicionarioConstrutos[construto.operando.constructor.name](construto.operando);
|
|
329
|
+
const operador = construto.operador.lexema;
|
|
330
|
+
this.emitirCarga('a0', operando);
|
|
331
|
+
if (operador === '-') {
|
|
332
|
+
this.text += `\n neg a0, a0`;
|
|
333
|
+
}
|
|
334
|
+
else if (operador === '!' || operador === 'nao') {
|
|
335
|
+
// seqz: a0 = 1 se a0 == 0, else 0
|
|
336
|
+
this.text += `\n seqz a0, a0`;
|
|
337
|
+
}
|
|
338
|
+
return 'a0';
|
|
339
|
+
}
|
|
340
|
+
traduzirConstrutoVariavel(construto) {
|
|
341
|
+
var _a;
|
|
342
|
+
const nomeVar = (_a = construto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
343
|
+
if (nomeVar && this.variaveis.has(nomeVar)) {
|
|
344
|
+
const varLabel = this.variaveis.get(nomeVar);
|
|
345
|
+
this.text += `
|
|
346
|
+
la a0, ${varLabel}
|
|
347
|
+
ld a0, 0(a0)`;
|
|
348
|
+
return 'a0';
|
|
349
|
+
}
|
|
350
|
+
return nomeVar || 'unknown';
|
|
351
|
+
}
|
|
352
|
+
traduzirConstrutoVetor(construto) {
|
|
353
|
+
const labelVetor = `vetor_${this.gerarDigitoAleatorio()}`;
|
|
354
|
+
// `elementos` filtra nós sintáticos (Separador, ComentarioComoConstruto)
|
|
355
|
+
const elementos = construto.elementos;
|
|
356
|
+
// Cada elemento ocupa 8 bytes em rv64
|
|
357
|
+
this.bss += ` ${labelVetor}: .space ${elementos.length * 8}\n`;
|
|
358
|
+
elementos.forEach((valor, index) => {
|
|
359
|
+
if (this.dicionarioConstrutos[valor.constructor.name]) {
|
|
360
|
+
const valorTraduzido = this.dicionarioConstrutos[valor.constructor.name](valor);
|
|
361
|
+
this.emitirCarga('a0', valorTraduzido);
|
|
362
|
+
this.text += `
|
|
363
|
+
la a1, ${labelVetor}
|
|
364
|
+
sd a0, ${index * 8}(a1)`;
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
return labelVetor;
|
|
368
|
+
}
|
|
369
|
+
// Implementação das Declarações
|
|
370
|
+
traduzirDeclaracaoBloco(declaracao) {
|
|
371
|
+
if (declaracao.declaracoes && Array.isArray(declaracao.declaracoes)) {
|
|
372
|
+
declaracao.declaracoes.forEach((decl) => {
|
|
373
|
+
if (this.dicionarioDeclaracoes[decl.constructor.name]) {
|
|
374
|
+
this.dicionarioDeclaracoes[decl.constructor.name](decl);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
traduzirDeclaracaoEnquanto(declaracao) {
|
|
380
|
+
const labelInicio = this.gerarLabel();
|
|
381
|
+
const labelFim = this.gerarLabel();
|
|
382
|
+
this.text += `\n${labelInicio}:`;
|
|
383
|
+
const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
|
|
384
|
+
if (condicao !== 'a0') {
|
|
385
|
+
this.emitirCarga('a0', condicao);
|
|
386
|
+
}
|
|
387
|
+
this.text += `\n beqz a0, ${labelFim}`;
|
|
388
|
+
if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
|
|
389
|
+
this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
|
|
390
|
+
}
|
|
391
|
+
this.text += `
|
|
392
|
+
j ${labelInicio}
|
|
393
|
+
${labelFim}:`;
|
|
394
|
+
}
|
|
395
|
+
traduzirDeclaracaoEscolha(declaracao) {
|
|
396
|
+
const labelFim = this.gerarLabel();
|
|
397
|
+
const valorEscolha = this.dicionarioConstrutos[declaracao.identificadorOuLiteral.constructor.name](declaracao.identificadorOuLiteral);
|
|
398
|
+
if (declaracao.caminhos && Array.isArray(declaracao.caminhos)) {
|
|
399
|
+
declaracao.caminhos.forEach((caminho) => {
|
|
400
|
+
const labelProximo = this.gerarLabel();
|
|
401
|
+
if (caminho.condicoes && caminho.condicoes[0]) {
|
|
402
|
+
const valorCaso = this.dicionarioConstrutos[caminho.condicoes[0].constructor.name](caminho.condicoes[0]);
|
|
403
|
+
this.emitirCarga('a0', valorEscolha);
|
|
404
|
+
this.emitirCarga('a1', valorCaso);
|
|
405
|
+
this.text += `\n bne a0, a1, ${labelProximo}`;
|
|
406
|
+
if (caminho.declaracoes && Array.isArray(caminho.declaracoes)) {
|
|
407
|
+
caminho.declaracoes.forEach((decl) => {
|
|
408
|
+
if (this.dicionarioDeclaracoes[decl.constructor.name]) {
|
|
409
|
+
this.dicionarioDeclaracoes[decl.constructor.name](decl);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
this.text += `
|
|
414
|
+
j ${labelFim}
|
|
415
|
+
${labelProximo}:`;
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
this.text += `\n${labelFim}:`;
|
|
420
|
+
}
|
|
421
|
+
traduzirDeclaracaoExpressao(declaracao) {
|
|
422
|
+
if (declaracao.expressao &&
|
|
423
|
+
this.dicionarioConstrutos[declaracao.expressao.constructor.name]) {
|
|
424
|
+
this.dicionarioConstrutos[declaracao.expressao.constructor.name](declaracao.expressao);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
traduzirDeclaracaoFazer(declaracao) {
|
|
428
|
+
const labelInicio = this.gerarLabel();
|
|
429
|
+
this.text += `\n${labelInicio}:`;
|
|
430
|
+
if (declaracao.caminhoFazer && declaracao.caminhoFazer.declaracoes) {
|
|
431
|
+
declaracao.caminhoFazer.declaracoes.forEach((decl) => {
|
|
432
|
+
if (this.dicionarioDeclaracoes[decl.constructor.name]) {
|
|
433
|
+
this.dicionarioDeclaracoes[decl.constructor.name](decl);
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (declaracao.condicaoEnquanto) {
|
|
438
|
+
const condicao = this.dicionarioConstrutos[declaracao.condicaoEnquanto.constructor.name](declaracao.condicaoEnquanto);
|
|
439
|
+
if (condicao !== 'a0') {
|
|
440
|
+
this.emitirCarga('a0', condicao);
|
|
441
|
+
}
|
|
442
|
+
this.text += `\n bnez a0, ${labelInicio}`;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
traduzirDeclaracaoFalhar(declaracao) {
|
|
446
|
+
let mensagem = '"Erro"';
|
|
447
|
+
if (declaracao.explicacao &&
|
|
448
|
+
typeof declaracao.explicacao === 'object' &&
|
|
449
|
+
'constructor' in declaracao.explicacao) {
|
|
450
|
+
const explicacao = declaracao.explicacao;
|
|
451
|
+
if (explicacao.constructor && this.dicionarioConstrutos[explicacao.constructor.name]) {
|
|
452
|
+
mensagem = this.dicionarioConstrutos[explicacao.constructor.name](explicacao);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
this.text += `
|
|
456
|
+
# Falhar com mensagem: ${mensagem}
|
|
457
|
+
li a0, 1
|
|
458
|
+
li a7, 93 # sys_exit
|
|
459
|
+
ecall`;
|
|
460
|
+
}
|
|
461
|
+
traduzirDeclaracaoFuncao(declaracao) {
|
|
462
|
+
var _a;
|
|
463
|
+
const nomeFuncao = ((_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'funcao';
|
|
464
|
+
this.text += `
|
|
465
|
+
|
|
466
|
+
${nomeFuncao}:
|
|
467
|
+
addi sp, sp, -16
|
|
468
|
+
sd ra, 8(sp)
|
|
469
|
+
sd s0, 0(sp)
|
|
470
|
+
addi s0, sp, 16`;
|
|
471
|
+
if (declaracao.funcao &&
|
|
472
|
+
declaracao.funcao.corpo &&
|
|
473
|
+
Array.isArray(declaracao.funcao.corpo)) {
|
|
474
|
+
declaracao.funcao.corpo.forEach((decl) => {
|
|
475
|
+
if (this.dicionarioDeclaracoes[decl.constructor.name]) {
|
|
476
|
+
this.dicionarioDeclaracoes[decl.constructor.name](decl);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
this.text += `
|
|
481
|
+
ld ra, 8(sp)
|
|
482
|
+
ld s0, 0(sp)
|
|
483
|
+
addi sp, sp, 16
|
|
484
|
+
ret`;
|
|
485
|
+
}
|
|
486
|
+
traduzirDeclaracaoImportar(declaracao) {
|
|
487
|
+
this.text += `\n # Importar: ${declaracao.caminho || 'unknown'}`;
|
|
488
|
+
}
|
|
489
|
+
traduzirDeclaracaoLeia(declaracao) {
|
|
490
|
+
var _a;
|
|
491
|
+
let nomeVar;
|
|
492
|
+
if (declaracao.argumentos &&
|
|
493
|
+
declaracao.argumentos[0] &&
|
|
494
|
+
declaracao.argumentos[0] instanceof construtos_1.Variavel) {
|
|
495
|
+
nomeVar = (_a = declaracao.argumentos[0].simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
496
|
+
}
|
|
497
|
+
if (!nomeVar)
|
|
498
|
+
return;
|
|
499
|
+
if (!this.variaveis.has(nomeVar)) {
|
|
500
|
+
const varLabel = `var_${nomeVar}`;
|
|
501
|
+
this.bss += ` ${varLabel}: .space 256\n`;
|
|
502
|
+
this.variaveis.set(nomeVar, varLabel);
|
|
503
|
+
}
|
|
504
|
+
this.text += `
|
|
505
|
+
li a0, 0 # fd stdin
|
|
506
|
+
la a1, ${this.variaveis.get(nomeVar)}
|
|
507
|
+
li a2, 256
|
|
508
|
+
li a7, 63 # sys_read
|
|
509
|
+
ecall`;
|
|
510
|
+
}
|
|
511
|
+
traduzirDeclaracaoPara(declaracao) {
|
|
512
|
+
const labelInicio = this.gerarLabel();
|
|
513
|
+
const labelFim = this.gerarLabel();
|
|
514
|
+
if (declaracao.inicializador) {
|
|
515
|
+
const tipoInicializador = declaracao.inicializador.constructor.name;
|
|
516
|
+
if (this.dicionarioDeclaracoes[tipoInicializador]) {
|
|
517
|
+
this.dicionarioDeclaracoes[tipoInicializador](declaracao.inicializador);
|
|
518
|
+
}
|
|
519
|
+
else if (this.dicionarioConstrutos[tipoInicializador]) {
|
|
520
|
+
this.dicionarioConstrutos[tipoInicializador](declaracao.inicializador);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
this.text += `\n${labelInicio}:`;
|
|
524
|
+
if (declaracao.condicao) {
|
|
525
|
+
const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
|
|
526
|
+
if (condicao !== 'a0') {
|
|
527
|
+
this.emitirCarga('a0', condicao);
|
|
528
|
+
}
|
|
529
|
+
this.text += `\n beqz a0, ${labelFim}`;
|
|
530
|
+
}
|
|
531
|
+
if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
|
|
532
|
+
this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
|
|
533
|
+
}
|
|
534
|
+
if (declaracao.incrementar) {
|
|
535
|
+
if (this.dicionarioConstrutos[declaracao.incrementar.constructor.name]) {
|
|
536
|
+
this.dicionarioConstrutos[declaracao.incrementar.constructor.name](declaracao.incrementar);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
this.text += `
|
|
540
|
+
j ${labelInicio}
|
|
541
|
+
${labelFim}:`;
|
|
542
|
+
}
|
|
543
|
+
traduzirDeclaracaoParaCada(declaracao) {
|
|
544
|
+
const labelInicio = this.gerarLabel();
|
|
545
|
+
const labelFim = this.gerarLabel();
|
|
546
|
+
const vetor = declaracao.vetorOuDicionario;
|
|
547
|
+
let tamanhoVetor = 0;
|
|
548
|
+
if (vetor instanceof construtos_1.Vetor) {
|
|
549
|
+
tamanhoVetor = vetor.tamanho || 0;
|
|
550
|
+
}
|
|
551
|
+
// t0: contador; t1: limite (caller-saved, seguros aqui)
|
|
552
|
+
this.text += `
|
|
553
|
+
li t0, 0 # contador
|
|
554
|
+
li t1, ${tamanhoVetor}
|
|
555
|
+
${labelInicio}:
|
|
556
|
+
bge t0, t1, ${labelFim}`;
|
|
557
|
+
if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
|
|
558
|
+
this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
|
|
559
|
+
}
|
|
560
|
+
this.text += `
|
|
561
|
+
addi t0, t0, 1
|
|
562
|
+
j ${labelInicio}
|
|
563
|
+
${labelFim}:`;
|
|
564
|
+
}
|
|
565
|
+
traduzirDeclaracaoRetorna(declaracao) {
|
|
566
|
+
if (declaracao.valor) {
|
|
567
|
+
const valor = this.dicionarioConstrutos[declaracao.valor.constructor.name](declaracao.valor);
|
|
568
|
+
this.emitirCarga('a0', valor);
|
|
569
|
+
}
|
|
570
|
+
this.text += `
|
|
571
|
+
ld ra, 8(sp)
|
|
572
|
+
ld s0, 0(sp)
|
|
573
|
+
addi sp, sp, 16
|
|
574
|
+
ret`;
|
|
575
|
+
}
|
|
576
|
+
traduzirDeclaracaoSe(declaracao) {
|
|
577
|
+
const labelSenao = this.gerarLabel();
|
|
578
|
+
const labelFim = this.gerarLabel();
|
|
579
|
+
const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
|
|
580
|
+
if (condicao !== 'a0') {
|
|
581
|
+
this.emitirCarga('a0', condicao);
|
|
582
|
+
}
|
|
583
|
+
this.text += `\n beqz a0, ${labelSenao}`;
|
|
584
|
+
if (this.dicionarioDeclaracoes[declaracao.caminhoEntao.constructor.name]) {
|
|
585
|
+
this.dicionarioDeclaracoes[declaracao.caminhoEntao.constructor.name](declaracao.caminhoEntao);
|
|
586
|
+
}
|
|
587
|
+
this.text += `
|
|
588
|
+
j ${labelFim}
|
|
589
|
+
${labelSenao}:`;
|
|
590
|
+
if (declaracao.caminhoSenao &&
|
|
591
|
+
this.dicionarioDeclaracoes[declaracao.caminhoSenao.constructor.name]) {
|
|
592
|
+
this.dicionarioDeclaracoes[declaracao.caminhoSenao.constructor.name](declaracao.caminhoSenao);
|
|
593
|
+
}
|
|
594
|
+
this.text += `\n${labelFim}:`;
|
|
595
|
+
}
|
|
596
|
+
traduzirDeclaracaoClasse(declaracao) {
|
|
597
|
+
var _a;
|
|
598
|
+
this.text += `\n # Classe: ${((_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'unknown'}`;
|
|
599
|
+
}
|
|
600
|
+
traduzirDeclaracaoTente(declaracao) {
|
|
601
|
+
this.text += `\n # Tente-pegue`;
|
|
602
|
+
if (declaracao.caminhoTente && Array.isArray(declaracao.caminhoTente)) {
|
|
603
|
+
declaracao.caminhoTente.forEach((decl) => {
|
|
604
|
+
if (this.dicionarioDeclaracoes[decl.constructor.name]) {
|
|
605
|
+
this.dicionarioDeclaracoes[decl.constructor.name](decl);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
traduzirDeclaracaoConst(declaracao) {
|
|
611
|
+
var _a;
|
|
612
|
+
const nomeVar = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
613
|
+
if (!nomeVar)
|
|
614
|
+
return;
|
|
615
|
+
const valor = this.dicionarioConstrutos[declaracao.inicializador.constructor.name](declaracao.inicializador);
|
|
616
|
+
const varLabel = `const_${nomeVar}`;
|
|
617
|
+
this.data += ` ${varLabel}: .dword ${valor}\n`;
|
|
618
|
+
this.variaveis.set(nomeVar, varLabel);
|
|
619
|
+
}
|
|
620
|
+
traduzirDeclaracaoVar(declaracao) {
|
|
621
|
+
var _a;
|
|
622
|
+
const nomeVar = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
|
|
623
|
+
if (!nomeVar)
|
|
624
|
+
return;
|
|
625
|
+
const varLabel = `var_${nomeVar}`;
|
|
626
|
+
this.bss += ` ${varLabel}: .space 8\n`;
|
|
627
|
+
this.variaveis.set(nomeVar, varLabel);
|
|
628
|
+
if (declaracao.inicializador && declaracao.inicializador.valor !== null) {
|
|
629
|
+
const tipoInicializador = declaracao.inicializador.constructor.name;
|
|
630
|
+
if (declaracao.inicializador instanceof construtos_1.Vetor) {
|
|
631
|
+
const labelVetor = this.traduzirConstrutoVetor(declaracao.inicializador);
|
|
632
|
+
this.variaveis.set(nomeVar, labelVetor);
|
|
633
|
+
}
|
|
634
|
+
else if (this.dicionarioConstrutos[tipoInicializador]) {
|
|
635
|
+
const valor = this.dicionarioConstrutos[tipoInicializador](declaracao.inicializador);
|
|
636
|
+
this.emitirCarga('a0', valor);
|
|
637
|
+
this.text += `
|
|
638
|
+
la a1, ${varLabel}
|
|
639
|
+
sd a0, 0(a1)`;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
criaStringLiteral(literal) {
|
|
644
|
+
const varLiteral = `Delegua_${this.gerarDigitoAleatorio()}`;
|
|
645
|
+
this.data += ` ${varLiteral}: .asciz "${literal.valor}"\n`;
|
|
646
|
+
return varLiteral;
|
|
647
|
+
}
|
|
648
|
+
criaTamanhoNaMemoriaReferenteAVar(nomeStringLiteral) {
|
|
649
|
+
return `tam_${nomeStringLiteral}`;
|
|
650
|
+
}
|
|
651
|
+
traduzirDeclaracaoEscreva(declaracaoEscreva) {
|
|
652
|
+
let nomeStringLiteral = '';
|
|
653
|
+
let tamanhoString = '';
|
|
654
|
+
if (declaracaoEscreva.argumentos[0] instanceof construtos_1.Literal) {
|
|
655
|
+
nomeStringLiteral = this.criaStringLiteral(declaracaoEscreva.argumentos[0]);
|
|
656
|
+
const stringValue = declaracaoEscreva.argumentos[0].valor;
|
|
657
|
+
tamanhoString = String(stringValue.length);
|
|
658
|
+
}
|
|
659
|
+
// sys_write(fd=1, buf, count): a7=64, a0=fd, a1=buf, a2=count
|
|
660
|
+
this.text += `
|
|
661
|
+
la a1, ${nomeStringLiteral}
|
|
662
|
+
li a2, ${tamanhoString}
|
|
663
|
+
li a0, 1 # fd stdout
|
|
664
|
+
li a7, 64 # sys_write
|
|
665
|
+
ecall`;
|
|
666
|
+
}
|
|
667
|
+
saidaSistema() {
|
|
668
|
+
this.text += `
|
|
669
|
+
li a0, 0 # código de saída
|
|
670
|
+
li a7, 93 # sys_exit
|
|
671
|
+
ecall`;
|
|
672
|
+
}
|
|
673
|
+
traduzir(declaracoes) {
|
|
674
|
+
this.declaracoesDeClasses = declaracoes.filter((declaracao) => declaracao instanceof declaracoes_1.Classe);
|
|
675
|
+
for (const declaracao of declaracoes) {
|
|
676
|
+
if (this.dicionarioDeclaracoes[declaracao.constructor.name]) {
|
|
677
|
+
this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
this.saidaSistema();
|
|
681
|
+
return this.bss + '\n' + this.data + '\n' + this.text;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
exports.TradutorAssemblyRISCV = TradutorAssemblyRISCV;
|
|
685
|
+
//# sourceMappingURL=tradutor-assembly-risc-v.js.map
|