Skip to content

Commit

Permalink
Correção nas verificações de erros relacionados a escopo e tipos
Browse files Browse the repository at this point in the history
Closes #196
Closes #206
Closes #207
  • Loading branch information
dgadelha committed Apr 30, 2024
1 parent a5d14c7 commit 135d204
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 16 deletions.
6 changes: 5 additions & 1 deletion packages/ide/src/app/tab-start/tab-start.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@

<section class="info">
<h4><svg-icon src="assets/mdi/newspaper.svg" svgAriaLabel="Ícone de jornal para notícias" />Novidades</h4>
<p><strong>30/04/2024:</strong> Melhorias de acessibilidade e ajustes na tela inicial e ícones</p>
<p><strong>30/04/2024:</strong></p>
<ul>
<li>Melhorias de acessibilidade e ajustes na tela inicial e ícones</li>
<li>Correção nas verificações de erros relacionados a escopo e tipos</li>
</ul>
<p><strong>10/03/2024:</strong> Otimização de desempenho na análise semântica</p>
<p><strong>09/03/2024:</strong> Novo domínio: <strong>portugol.dev</strong> e experimento com propagandas</p>
</section>
Expand Down
48 changes: 47 additions & 1 deletion packages/parser/src/errors/02-variáveis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ParaCmd,
Parâmetro,
ReferênciaVarExpr,
RetorneCmd,
SeCmd,
} from "../nodes/index.js";

Expand All @@ -37,6 +38,19 @@ export function* checarUsoEscopo(arquivo: Arquivo): Generator<PortugolCodeError>
break;
}

case Função: {
const func = as Função;

escopo.funções.set(func.nome, func.retorno);
escopo.push();
escopo.função = func.retorno;

yield* varrerNós(.children);

escopo.pop();
break;
}

case ReferênciaVarExpr: {
const ref = as ReferênciaVarExpr;

Expand Down Expand Up @@ -93,7 +107,6 @@ export function* checarUsoEscopo(arquivo: Arquivo): Generator<PortugolCodeError>
case EnquantoCmd:
case EscolhaCmd:
case FaçaEnquantoCmd:
case Função:
case ParaCmd: {
escopo.push();
yield* varrerNós(.children);
Expand All @@ -118,6 +131,39 @@ export function* checarUsoEscopo(arquivo: Arquivo): Generator<PortugolCodeError>
break;
}

case RetorneCmd: {
const ret = as RetorneCmd;

if (ret.expressão) {
yield* varrerNó(ret.expressão);
}

if (escopo.função) {
try {
const tret = resolverResultadoExpressão(ret.expressão, escopo);

if (
TabelaCompatibilidadeAtribuição[escopo.função.primitivo][tret] === ResultadoCompatibilidade.INCOMPATÍVEL
) {
yield PortugolCodeError.fromContext(
ret.ctx,
`Não é possível retornar um valor do tipo '${tret}' em uma função que retorna '${escopo.função.primitivo}'`,
);
}
} catch (error) {
const message = error instanceof Error ? error.message : "Não foi possível resolver o tipo da expressão";

if (message === "TODO") {
break;
}

yield PortugolCodeError.fromContext(ret.ctx, message);
}
}

break;
}

default: {
yield* varrerNós(.children);
break;
Expand Down
35 changes: 33 additions & 2 deletions packages/parser/src/helpers/Escopo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Tipo, TipoPrimitivo } from "./Tipo.js";
interface IEscopo {
variáveis: Map<string, Tipo>;
funções: Map<string, Tipo>;
função?: Tipo;
}

export class Escopo {
Expand All @@ -22,7 +23,11 @@ export class Escopo {
}

push() {
this.pilha.push({ variáveis: new Map(), funções: new Map() });
this.pilha.push({
variáveis: new Map(),
funções: new Map(),
função: this.atual.função,
});
}

pop() {
Expand All @@ -49,6 +54,14 @@ export class Escopo {
return this.atual.funções;
}

get função(): Tipo | undefined {
return this.atual.função;
}

set função(tipo: Tipo) {
this.atual.função = tipo;
}

hasVariável(nome: string) {
for (const escopo of this.pilha) {
if (escopo.variáveis.has(nome)) {
Expand All @@ -60,14 +73,32 @@ export class Escopo {
}

hasFunção(nome: string) {
return this.funções.has(nome);
for (const escopo of this.pilha) {
if (escopo.funções.has(nome)) {
return true;
}
}

return false;
}

getVariável(nome: string) {
for (const escopo of this.pilha) {
if (escopo.variáveis.has(nome)) {
return escopo.variáveis.get(nome);
}
}

return this.variáveis.get(nome);
}

getFunção(nome: string) {
for (const escopo of this.pilha) {
if (escopo.funções.has(nome)) {
return escopo.funções.get(nome);
}
}

return this.funções.get(nome);
}
}
28 changes: 16 additions & 12 deletions packages/parser/src/helpers/expressões.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
import {
ResultadoCompatibilidade,
TabelaCompatibilidadeBitwise,
TabelaCompatibilidadeDiferençaIgualdade,
TabelaCompatibilidadeDivisãoMultiplicaçãoSubtração,
TabelaCompatibilidadeEOu,
TabelaCompatibilidadeModulo,
TabelaCompatibilidadeSoma,
} from "./compatibilidade.js";
import { Escopo } from "./Escopo.js";
import { TipoPrimitivo } from "./Tipo.js";
import { Expressão } from "../nodes/Expressão.js";
import {
CadeiaExpr,
Expand Down Expand Up @@ -50,8 +39,23 @@ import {
SubtraçãoExpr,
VazioExpr,
} from "../nodes/index.js";
import { Escopo } from "./Escopo.js";
import { TipoPrimitivo } from "./Tipo.js";
import {
ResultadoCompatibilidade,
TabelaCompatibilidadeBitwise,
TabelaCompatibilidadeDiferençaIgualdade,
TabelaCompatibilidadeDivisãoMultiplicaçãoSubtração,
TabelaCompatibilidadeEOu,
TabelaCompatibilidadeModulo,
TabelaCompatibilidadeSoma,
} from "./compatibilidade.js";

export function resolverResultadoExpressão(expressão: Expressão | undefined, escopo: Escopo): TipoPrimitivo {
if (!expressão) {
return TipoPrimitivo.VAZIO;
}

export function resolverResultadoExpressão(expressão: Expressão, escopo: Escopo): TipoPrimitivo {
switch (expressão.constructor) {
case CadeiaExpr: {
return TipoPrimitivo.CADEIA;
Expand Down

0 comments on commit 135d204

Please sign in to comment.