@designliquido/delegua 1.24.0 → 1.24.2

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/umd/delegua.js CHANGED
@@ -553,6 +553,10 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
553
553
  // Chamadas de método/função podem retornar vetores.
554
554
  // A validação detalhada é feita em tempo de execução.
555
555
  }
556
+ else if (declaracao.inicializador instanceof construtos_1.Binario) {
557
+ // Expressões binárias podem produzir vetores em tempo de execução
558
+ // (ex: vetor1 + vetor2 concatena dois vetores), então não geramos erro
559
+ }
556
560
  else {
557
561
  this.erro(declaracao.simbolo, `Atribuição inválida para '${declaracao.simbolo.lexema}': é esperado um vetor de elementos.`);
558
562
  }
@@ -2201,7 +2205,7 @@ class AvaliadorSintaticoBase {
2201
2205
  async unario() {
2202
2206
  if (this.verificarSeSimboloAtualEIgualA(comum_1.default.NEGACAO, comum_1.default.SUBTRACAO)) {
2203
2207
  const operador = this.simbolos[this.atual - 1];
2204
- const direito = await this.unario();
2208
+ const direito = await this.exponenciacao();
2205
2209
  return Promise.resolve(new construtos_1.Unario(this.hashArquivo, operador, direito, 'ANTES'));
2206
2210
  }
2207
2211
  return await this.chamar();
@@ -3374,7 +3378,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
3374
3378
  }
3375
3379
  if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.NAO, delegua_2.default.NEGACAO, delegua_2.default.ADICAO, delegua_2.default.SUBTRACAO, delegua_2.default.BIT_NOT, delegua_2.default.INCREMENTAR, delegua_2.default.DECREMENTAR)) {
3376
3380
  const operador = this.simbolos[this.atual - 1];
3377
- const direito = await this.unario();
3381
+ const direito = await this.exponenciacao();
3378
3382
  if (operador.tipo === delegua_2.default.NEGACAO ||
3379
3383
  operador.tipo === delegua_2.default.NAO) {
3380
3384
  this.verificarOperandoNegacao(operador, direito);
@@ -4634,6 +4638,289 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
4634
4638
  this.interfacesDeclaradas[simbolo.lexema] = declaracao;
4635
4639
  return declaracao;
4636
4640
  }
4641
+ async analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual) {
4642
+ const simboloOperadorKeyword = this.avancarEDevolverAnterior();
4643
+ const simboloDoOperador = this.avancarEDevolverAnterior();
4644
+ const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
4645
+ const simboloNomeMetodo = {
4646
+ tipo: delegua_2.default.IDENTIFICADOR,
4647
+ lexema: nomeMetodoOp,
4648
+ literal: null,
4649
+ linha: simboloOperadorKeyword.linha,
4650
+ hashArquivo: this.hashArquivo,
4651
+ };
4652
+ this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
4653
+ let paramsOp = [];
4654
+ if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4655
+ paramsOp = await this.logicaComumParametros();
4656
+ }
4657
+ this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
4658
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
4659
+ const indiceAberturaCorpoOp = this.atual - 1;
4660
+ const quantidadeErrosAntesCorpoOp = this.erros.length;
4661
+ let corpoOp = [];
4662
+ try {
4663
+ corpoOp = await this.blocoEscopo();
4664
+ }
4665
+ catch (erro) {
4666
+ this.erros.push(erro);
4667
+ }
4668
+ if (this.erros.length > quantidadeErrosAntesCorpoOp) {
4669
+ this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
4670
+ corpoOp = [];
4671
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4672
+ }
4673
+ const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
4674
+ const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
4675
+ metodoOp.estatico = ehEstatico;
4676
+ metodoOp.acesso = modificadorAcesso;
4677
+ metodoOp.documentacao = docAtual;
4678
+ metodos.push(metodoOp);
4679
+ this.pilhaDecoradores = [];
4680
+ }
4681
+ async analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual) {
4682
+ const nomeMetodo = this.avancarEDevolverAnterior();
4683
+ // Pré-registrar para suportar chamadas recursivas (igual a funcao()).
4684
+ this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
4685
+ this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
4686
+ let params = [];
4687
+ if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4688
+ params = await this.logicaComumParametros();
4689
+ }
4690
+ this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
4691
+ let tipoRetorno = 'qualquer';
4692
+ let definicaoExplicitaDeTipo = false;
4693
+ if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
4694
+ tipoRetorno = this.verificarDefinicaoTipoAtual();
4695
+ this.avancarEDevolverAnterior();
4696
+ definicaoExplicitaDeTipo = true;
4697
+ }
4698
+ if (ehEstrangeira && this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
4699
+ throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
4700
+ }
4701
+ // Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
4702
+ // ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
4703
+ const ehAbstrato = ehAbstratoPadrao ||
4704
+ ehEstrangeira ||
4705
+ (ehAbstrata && !this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
4706
+ if (ehAbstrato) {
4707
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4708
+ const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
4709
+ const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
4710
+ metodoAbstrato.estatico = ehEstatico;
4711
+ metodoAbstrato.abstrato = true;
4712
+ metodoAbstrato.acesso = modificadorAcesso;
4713
+ metodoAbstrato.decoradores = Array.from(this.pilhaDecoradores);
4714
+ metodoAbstrato.documentacao = docAtual;
4715
+ metodos.push(metodoAbstrato);
4716
+ }
4717
+ else {
4718
+ // Método concreto: com corpo. Inferência de tipo de retorno igual a corpoDaFuncao().
4719
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
4720
+ const indiceAberturaCorpo = this.atual - 1;
4721
+ const quantidadeErrosAntesCorpo = this.erros.length;
4722
+ let corpo = [];
4723
+ try {
4724
+ corpo = await this.blocoEscopo();
4725
+ }
4726
+ catch (erro) {
4727
+ this.erros.push(erro);
4728
+ }
4729
+ if (this.erros.length > quantidadeErrosAntesCorpo) {
4730
+ this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
4731
+ corpo = [];
4732
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4733
+ }
4734
+ let expressoesRetorna = [];
4735
+ for (const declaracao of corpo) {
4736
+ expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
4737
+ }
4738
+ const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
4739
+ const retornaChamadoExplicitamente = tiposRetornos.size > 0;
4740
+ tiposRetornos.delete('qualquer');
4741
+ if (tipoRetorno === 'qualquer') {
4742
+ if (tiposRetornos.size > 0) {
4743
+ tipoRetorno = tiposRetornos.values().next().value;
4744
+ }
4745
+ else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
4746
+ tipoRetorno = 'vazio';
4747
+ }
4748
+ }
4749
+ const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
4750
+ const tipoDaFuncao = `função<${tipoRetorno}>`;
4751
+ const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
4752
+ metodo.estatico = ehEstatico;
4753
+ metodo.acesso = modificadorAcesso;
4754
+ metodo.decoradores = Array.from(this.pilhaDecoradores);
4755
+ metodo.documentacao = docAtual;
4756
+ metodos.push(metodo);
4757
+ this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
4758
+ this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
4759
+ }
4760
+ this.pilhaDecoradores = [];
4761
+ }
4762
+ async analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual) {
4763
+ const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
4764
+ this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
4765
+ const tipoPropriedade = this.avancarEDevolverAnterior();
4766
+ let nomeTipoPropriedade = tipoPropriedade.lexema;
4767
+ if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
4768
+ this.avancarEDevolverAnterior();
4769
+ this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
4770
+ nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
4771
+ }
4772
+ const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
4773
+ prop.documentacao = docAtual;
4774
+ // Auto-propriedade: `nome: tipo { obter; definir; }`
4775
+ // Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
4776
+ if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
4777
+ this.avancarEDevolverAnterior();
4778
+ let temCorpoPersonalizado = false;
4779
+ while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
4780
+ const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
4781
+ if (lexema === 'obter' || lexema === 'definir') {
4782
+ const ehObter = lexema === 'obter';
4783
+ this.avancarEDevolverAnterior();
4784
+ if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
4785
+ // Corpo personalizado: obter() { ... } / definir(valor) { ... }
4786
+ temCorpoPersonalizado = true;
4787
+ this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
4788
+ let paramsAcessor = [];
4789
+ if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4790
+ paramsAcessor = await this.logicaComumParametros();
4791
+ }
4792
+ this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
4793
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
4794
+ const indiceAberturaCorpoAcessor = this.atual - 1;
4795
+ const quantidadeErrosAntesCorpoAcessor = this.erros.length;
4796
+ let corpoAcessor = [];
4797
+ try {
4798
+ corpoAcessor = await this.blocoEscopo();
4799
+ }
4800
+ catch (erro) {
4801
+ this.erros.push(erro);
4802
+ }
4803
+ if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
4804
+ this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
4805
+ corpoAcessor = [];
4806
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4807
+ }
4808
+ let tipoAcessor = 'qualquer';
4809
+ let expressoesRetornaAcessor = [];
4810
+ for (const declaracao of corpoAcessor) {
4811
+ expressoesRetornaAcessor = expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
4812
+ }
4813
+ const tiposRetornosAcessor = new Set(expressoesRetornaAcessor.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
4814
+ const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
4815
+ tiposRetornosAcessor.delete('qualquer');
4816
+ if (tiposRetornosAcessor.size > 0) {
4817
+ tipoAcessor = tiposRetornosAcessor.values().next().value;
4818
+ }
4819
+ else if (!retornaExplicitamenteAcessor) {
4820
+ tipoAcessor = 'vazio';
4821
+ }
4822
+ const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
4823
+ const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
4824
+ const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
4825
+ metodoAcessor.estatico = ehEstatico;
4826
+ metodoAcessor.acesso = modificadorAcesso;
4827
+ metodoAcessor.eObtenedor = ehObter;
4828
+ metodoAcessor.eDefinidor = !ehObter;
4829
+ metodos.push(metodoAcessor);
4830
+ }
4831
+ else {
4832
+ // Forma trivial: obter; / definir;
4833
+ if (ehObter) {
4834
+ prop.autoObter = true;
4835
+ }
4836
+ else {
4837
+ prop.autoDefinir = true;
4838
+ }
4839
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4840
+ }
4841
+ }
4842
+ else {
4843
+ break;
4844
+ }
4845
+ }
4846
+ this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
4847
+ // Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
4848
+ // Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
4849
+ // nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
4850
+ if (!temCorpoPersonalizado) {
4851
+ propriedades.push(prop);
4852
+ }
4853
+ }
4854
+ else {
4855
+ this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4856
+ propriedades.push(prop);
4857
+ }
4858
+ this.pilhaDecoradores = [];
4859
+ }
4860
+ async compreenderMembros(acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades) {
4861
+ while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
4862
+ !this.estaNoFinal()) {
4863
+ if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
4864
+ this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
4865
+ this.avancarEDevolverAnterior();
4866
+ continue;
4867
+ }
4868
+ let docAtual = undefined;
4869
+ if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
4870
+ const simboloDoc = this.avancarEDevolverAnterior();
4871
+ docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
4872
+ }
4873
+ if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
4874
+ await this.resolverDecoradores();
4875
+ continue;
4876
+ }
4877
+ const tipoAtual = this.simbolos[this.atual].tipo;
4878
+ const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
4879
+ const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
4880
+ tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4881
+ const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4882
+ const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4883
+ if (ehBlocoAcesso) {
4884
+ const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
4885
+ this.avancarEDevolverAnterior();
4886
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
4887
+ await this.compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
4888
+ this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
4889
+ continue;
4890
+ }
4891
+ if (ehBlocoEstatico) {
4892
+ this.avancarEDevolverAnterior();
4893
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
4894
+ await this.compreenderMembros(acessoPadrao, true, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
4895
+ this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
4896
+ continue;
4897
+ }
4898
+ if (ehBlocoAbstrato) {
4899
+ this.avancarEDevolverAnterior();
4900
+ this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
4901
+ await this.compreenderMembros(acessoPadrao, ehEstaticoPadrao, true, ehAbstrata, ehEstrangeira, metodos, propriedades);
4902
+ this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
4903
+ continue;
4904
+ }
4905
+ const modificadorAcesso = acessoPadrao;
4906
+ const ehEstatico = ehEstaticoPadrao;
4907
+ if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
4908
+ await this.analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual);
4909
+ continue;
4910
+ }
4911
+ const proximoSimbolo = this.simbolos[this.atual + 1];
4912
+ switch (proximoSimbolo?.tipo) {
4913
+ case delegua_2.default.PARENTESE_ESQUERDO:
4914
+ await this.analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual);
4915
+ break;
4916
+ case delegua_2.default.DOIS_PONTOS:
4917
+ await this.analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual);
4918
+ break;
4919
+ default:
4920
+ throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
4921
+ }
4922
+ }
4923
+ }
4637
4924
  async declaracaoDeClasse() {
4638
4925
  // Modificadores opcionais no nível da classe: `abstrata`, `estrangeira` e/ou `estática`.
4639
4926
  // Sintaxe: `classe abstrata NomeDaClasse`, `classe estrangeira NomeDaClasse`, etc.
@@ -4685,314 +4972,8 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
4685
4972
  this.pilhaDecoradores = [];
4686
4973
  const metodos = [];
4687
4974
  const propriedades = [];
4688
- /**
4689
- * Analisa membros do corpo da classe com um contexto de acesso e estático padrão.
4690
- * Suporta blocos de contexto aninhados: `estático { }`, `abstrato { }`, `privado { }`, `protegido { }`, `publico { }`.
4691
- */
4692
- const compreenderMembros = async (acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao = false) => {
4693
- while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
4694
- !this.estaNoFinal()) {
4695
- // Pular comentários normais dentro do corpo da classe.
4696
- if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
4697
- this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
4698
- this.avancarEDevolverAnterior();
4699
- continue;
4700
- }
4701
- // Documentário (/** ... */)
4702
- let docAtual = undefined;
4703
- if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
4704
- const simboloDoc = this.avancarEDevolverAnterior();
4705
- docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
4706
- }
4707
- // Decorador
4708
- if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
4709
- await this.resolverDecoradores();
4710
- continue;
4711
- }
4712
- // Detecção de bloco de contexto: modificador seguido de '{'
4713
- const tipoAtual = this.simbolos[this.atual].tipo;
4714
- const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
4715
- const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
4716
- tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4717
- const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO &&
4718
- tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4719
- const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO &&
4720
- tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
4721
- if (ehBlocoAcesso) {
4722
- const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
4723
- this.avancarEDevolverAnterior(); // consume modificador de acesso
4724
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
4725
- await compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao);
4726
- this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
4727
- continue;
4728
- }
4729
- if (ehBlocoEstatico) {
4730
- this.avancarEDevolverAnterior(); // consume 'estático'
4731
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
4732
- await compreenderMembros(acessoPadrao, true, ehAbstratoPadrao);
4733
- this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
4734
- continue;
4735
- }
4736
- if (ehBlocoAbstrato) {
4737
- this.avancarEDevolverAnterior(); // consume 'abstrato'
4738
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
4739
- await compreenderMembros(acessoPadrao, ehEstaticoPadrao, true);
4740
- this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
4741
- continue;
4742
- }
4743
- const modificadorAcesso = acessoPadrao;
4744
- const ehEstatico = ehEstaticoPadrao;
4745
- // Método operador sobrecarregado: `operador+ (outro) { ... }`
4746
- if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
4747
- const simboloOperadorKeyword = this.avancarEDevolverAnterior();
4748
- const simboloDoOperador = this.avancarEDevolverAnterior();
4749
- const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
4750
- const simboloNomeMetodo = {
4751
- tipo: delegua_2.default.IDENTIFICADOR,
4752
- lexema: nomeMetodoOp,
4753
- literal: null,
4754
- linha: simboloOperadorKeyword.linha,
4755
- hashArquivo: this.hashArquivo,
4756
- };
4757
- this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
4758
- let paramsOp = [];
4759
- if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4760
- paramsOp = await this.logicaComumParametros();
4761
- }
4762
- this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
4763
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
4764
- const indiceAberturaCorpoOp = this.atual - 1;
4765
- const quantidadeErrosAntesCorpoOp = this.erros.length;
4766
- let corpoOp = [];
4767
- try {
4768
- corpoOp = await this.blocoEscopo();
4769
- }
4770
- catch (erro) {
4771
- this.erros.push(erro);
4772
- }
4773
- if (this.erros.length > quantidadeErrosAntesCorpoOp) {
4774
- this.atual =
4775
- this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
4776
- corpoOp = [];
4777
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4778
- }
4779
- const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
4780
- const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
4781
- metodoOp.estatico = ehEstatico;
4782
- metodoOp.acesso = modificadorAcesso;
4783
- metodoOp.documentacao = docAtual;
4784
- metodos.push(metodoOp);
4785
- this.pilhaDecoradores = [];
4786
- continue;
4787
- }
4788
- // Método ou propriedade, determinado pelo token seguinte ao nome
4789
- const proximoSimbolo = this.simbolos[this.atual + 1];
4790
- switch (proximoSimbolo?.tipo) {
4791
- case delegua_2.default.PARENTESE_ESQUERDO: {
4792
- // Analisa: nome ( params ) [abstrato] [: tipoRetorno] { corpo }
4793
- const nomeMetodo = this.avancarEDevolverAnterior();
4794
- // Pré-registrar para suportar chamadas recursivas (igual a funcao()).
4795
- this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
4796
- this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
4797
- let params = [];
4798
- if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4799
- params = await this.logicaComumParametros();
4800
- }
4801
- this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
4802
- // Tipo de retorno opcional (igual a corpoDaFuncao())
4803
- let tipoRetorno = 'qualquer';
4804
- let definicaoExplicitaDeTipo = false;
4805
- if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
4806
- tipoRetorno = this.verificarDefinicaoTipoAtual();
4807
- this.avancarEDevolverAnterior();
4808
- definicaoExplicitaDeTipo = true;
4809
- }
4810
- // Método de classe estrangeira não pode ter corpo.
4811
- if (ehEstrangeira &&
4812
- this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
4813
- throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
4814
- }
4815
- // Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
4816
- // ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
4817
- const ehAbstrato = ehAbstratoPadrao ||
4818
- ehEstrangeira ||
4819
- (ehAbstrata &&
4820
- !this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
4821
- if (ehAbstrato) {
4822
- // Método abstrato/estrangeiro: sem corpo
4823
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4824
- const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
4825
- const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
4826
- metodoAbstrato.estatico = ehEstatico;
4827
- metodoAbstrato.abstrato = true;
4828
- metodoAbstrato.acesso = modificadorAcesso;
4829
- metodoAbstrato.documentacao = docAtual;
4830
- metodos.push(metodoAbstrato);
4831
- }
4832
- else {
4833
- // Método concreto: com corpo.
4834
- // Inferência de tipo de retorno igual a corpoDaFuncao().
4835
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
4836
- const indiceAberturaCorpo = this.atual - 1;
4837
- const quantidadeErrosAntesCorpo = this.erros.length;
4838
- let corpo = [];
4839
- try {
4840
- corpo = await this.blocoEscopo();
4841
- }
4842
- catch (erro) {
4843
- this.erros.push(erro);
4844
- }
4845
- if (this.erros.length > quantidadeErrosAntesCorpo) {
4846
- this.atual =
4847
- this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
4848
- corpo = [];
4849
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4850
- }
4851
- let expressoesRetorna = [];
4852
- for (const declaracao of corpo) {
4853
- expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
4854
- }
4855
- const tiposRetornos = new Set(expressoesRetorna
4856
- .filter((e) => e.tipo !== 'qualquer')
4857
- .map((e) => e.tipo));
4858
- const retornaChamadoExplicitamente = tiposRetornos.size > 0;
4859
- tiposRetornos.delete('qualquer');
4860
- if (tipoRetorno === 'qualquer') {
4861
- if (tiposRetornos.size > 0) {
4862
- tipoRetorno = tiposRetornos.values().next().value;
4863
- }
4864
- else if (!retornaChamadoExplicitamente &&
4865
- !definicaoExplicitaDeTipo) {
4866
- tipoRetorno = 'vazio';
4867
- }
4868
- }
4869
- const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
4870
- const tipoDaFuncao = `função<${tipoRetorno}>`;
4871
- const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
4872
- metodo.estatico = ehEstatico;
4873
- metodo.acesso = modificadorAcesso;
4874
- metodo.decoradores = Array.from(this.pilhaDecoradores);
4875
- metodo.documentacao = docAtual;
4876
- metodos.push(metodo);
4877
- this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
4878
- this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
4879
- }
4880
- this.pilhaDecoradores = [];
4881
- break;
4882
- }
4883
- case delegua_2.default.DOIS_PONTOS: {
4884
- const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
4885
- this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
4886
- const tipoPropriedade = this.avancarEDevolverAnterior();
4887
- let nomeTipoPropriedade = tipoPropriedade.lexema;
4888
- if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
4889
- this.avancarEDevolverAnterior(); // consume '['
4890
- this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
4891
- nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
4892
- }
4893
- const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
4894
- prop.documentacao = docAtual;
4895
- // Auto-propriedade: `nome: tipo { obter; definir; }`
4896
- // Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
4897
- if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
4898
- this.avancarEDevolverAnterior(); // consume '{'
4899
- let temCorpoPersonalizado = false;
4900
- while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
4901
- !this.estaNoFinal()) {
4902
- const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
4903
- if (lexema === 'obter' || lexema === 'definir') {
4904
- const ehObter = lexema === 'obter';
4905
- this.avancarEDevolverAnterior(); // consume 'obter' / 'definir'
4906
- if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
4907
- // Corpo personalizado: obter() { ... } / definir(valor) { ... }
4908
- temCorpoPersonalizado = true;
4909
- this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
4910
- let paramsAcessor = [];
4911
- if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
4912
- paramsAcessor = await this.logicaComumParametros();
4913
- }
4914
- this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
4915
- this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
4916
- const indiceAberturaCorpoAcessor = this.atual - 1;
4917
- const quantidadeErrosAntesCorpoAcessor = this.erros.length;
4918
- let corpoAcessor = [];
4919
- try {
4920
- corpoAcessor = await this.blocoEscopo();
4921
- }
4922
- catch (erro) {
4923
- this.erros.push(erro);
4924
- }
4925
- if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
4926
- this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
4927
- corpoAcessor = [];
4928
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4929
- }
4930
- // Inferência de tipo de retorno
4931
- let tipoAcessor = 'qualquer';
4932
- let expressoesRetornaAcessor = [];
4933
- for (const declaracao of corpoAcessor) {
4934
- expressoesRetornaAcessor =
4935
- expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
4936
- }
4937
- const tiposRetornosAcessor = new Set(expressoesRetornaAcessor
4938
- .filter((e) => e.tipo !== 'qualquer')
4939
- .map((e) => e.tipo));
4940
- const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
4941
- tiposRetornosAcessor.delete('qualquer');
4942
- if (tiposRetornosAcessor.size > 0) {
4943
- tipoAcessor = tiposRetornosAcessor
4944
- .values()
4945
- .next().value;
4946
- }
4947
- else if (!retornaExplicitamenteAcessor) {
4948
- tipoAcessor = 'vazio';
4949
- }
4950
- const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
4951
- const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
4952
- const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
4953
- metodoAcessor.estatico = ehEstatico;
4954
- metodoAcessor.acesso = modificadorAcesso;
4955
- metodoAcessor.eObtenedor = ehObter;
4956
- metodoAcessor.eDefinidor = !ehObter;
4957
- metodos.push(metodoAcessor);
4958
- }
4959
- else {
4960
- // Forma trivial: obter; / definir;
4961
- if (ehObter) {
4962
- prop.autoObter = true;
4963
- }
4964
- else {
4965
- prop.autoDefinir = true;
4966
- }
4967
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4968
- }
4969
- }
4970
- else {
4971
- break;
4972
- }
4973
- }
4974
- this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
4975
- // Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
4976
- // Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
4977
- // nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
4978
- if (!temCorpoPersonalizado) {
4979
- propriedades.push(prop);
4980
- }
4981
- }
4982
- else {
4983
- this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
4984
- propriedades.push(prop);
4985
- }
4986
- this.pilhaDecoradores = [];
4987
- break;
4988
- }
4989
- default:
4990
- throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
4991
- }
4992
- }
4993
- };
4994
4975
  this.metodosClasseAtualEmAnalise = metodos;
4995
- await compreenderMembros('publico', false);
4976
+ await this.compreenderMembros('publico', false, false, ehAbstrata, ehEstrangeira, metodos, propriedades);
4996
4977
  this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
4997
4978
  // Verificação em tempo de análise: classe deve implementar todos os contratos das interfaces.
4998
4979
  const linhaFinalClasse = this.simbolos[this.atual - 1].linha;
@@ -7060,7 +7041,7 @@ class AvaliadorSintaticoPitugues extends avaliador_sintatico_base_1.AvaliadorSin
7060
7041
  }
7061
7042
  if (this.verificarSeSimboloAtualEIgualA(pitugues_2.default.NEGACAO, pitugues_2.default.SUBTRACAO, pitugues_2.default.BIT_NOT)) {
7062
7043
  const operador = this.simboloAnterior();
7063
- const direito = await this.unario();
7044
+ const direito = await this.exponenciacao();
7064
7045
  return new construtos_1.Unario(this.hashArquivo, operador, direito);
7065
7046
  }
7066
7047
  return await this.chamar();
@@ -7285,7 +7266,7 @@ class AvaliadorSintaticoPitugues extends avaliador_sintatico_base_1.AvaliadorSin
7285
7266
  const simboloOperador = new lexador_1.Simbolo(tipoOperadorMatematico, operadorAtribuicao.lexema.charAt(0), null, operadorAtribuicao.linha, operadorAtribuicao.hashArquivo);
7286
7267
  const operacaoBinaria = new construtos_1.Binario(this.hashArquivo, expressao, simboloOperador, valor);
7287
7268
  if (expressao instanceof construtos_1.Variavel) {
7288
- return new construtos_1.Atribuir(this.hashArquivo, expressao, operacaoBinaria);
7269
+ return new construtos_1.Atribuir(this.hashArquivo, expressao, operacaoBinaria, undefined, operadorAtribuicao);
7289
7270
  }
7290
7271
  if (expressao instanceof construtos_1.AcessoMetodoOuPropriedade) {
7291
7272
  return new construtos_1.DefinirValor(this.hashArquivo, 0, expressao.objeto, expressao.simbolo, operacaoBinaria);
@@ -22334,6 +22315,9 @@ class InterpretadorBase {
22334
22315
  // Se veio antes e o operando é uma variável, precisamos incrementar/decrementar,
22335
22316
  // armazenar o valor da variável pra só então devolver o valor.
22336
22317
  case delegua_1.default.INCREMENTAR:
22318
+ if (typeof valor === 'string') {
22319
+ throw new excecoes_1.ErroEmTempoDeExecucao(expressao.operador, `Operador '${expressao.operador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
22320
+ }
22337
22321
  if (expressao.incidenciaOperador === 'ANTES') {
22338
22322
  valor++;
22339
22323
  if (expressao.operando instanceof construtos_1.Variavel) {
@@ -22347,6 +22331,9 @@ class InterpretadorBase {
22347
22331
  }
22348
22332
  return valorAnteriorIncremento;
22349
22333
  case delegua_1.default.DECREMENTAR:
22334
+ if (typeof valor === 'string') {
22335
+ throw new excecoes_1.ErroEmTempoDeExecucao(expressao.operador, `Operador '${expressao.operador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
22336
+ }
22350
22337
  if (expressao.incidenciaOperador === 'ANTES') {
22351
22338
  valor--;
22352
22339
  if (expressao.operando instanceof construtos_1.Variavel) {
@@ -22886,6 +22873,31 @@ class InterpretadorBase {
22886
22873
  break;
22887
22874
  case construtos_1.Variavel:
22888
22875
  const alvoVariavel = expressao.alvo;
22876
+ if (expressao.simboloOperador) {
22877
+ let valorAtual;
22878
+ valorAtual = this.resolverValor(this.pilhaEscoposExecucao.obterValorVariavel(alvoVariavel.simbolo));
22879
+ if (typeof valorAtual === 'string') {
22880
+ let valorDireito;
22881
+ if (expressao.valor instanceof construtos_1.Binario) {
22882
+ valorDireito = this.resolverValor(await this.avaliar(expressao.valor.direita));
22883
+ }
22884
+ else {
22885
+ valorDireito = valorResolvido;
22886
+ }
22887
+ if (expressao.simboloOperador.tipo === delegua_1.default.MAIS_IGUAL) {
22888
+ if (typeof valorDireito !== 'string') {
22889
+ throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloOperador, `Operador '+=' não pode concatenar texto com ${typeof valorDireito}. Use conversão explícita.`, expressao.linha);
22890
+ }
22891
+ }
22892
+ else if ([delegua_1.default.MENOS_IGUAL,
22893
+ delegua_1.default.MULTIPLICACAO_IGUAL,
22894
+ delegua_1.default.DIVISAO_IGUAL,
22895
+ delegua_1.default.MODULO_IGUAL]
22896
+ .includes(expressao.simboloOperador.tipo)) {
22897
+ throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloOperador, `Operador '${expressao.simboloOperador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
22898
+ }
22899
+ }
22900
+ }
22889
22901
  this.atribuirVariavel(alvoVariavel, valorResolvido, indice);
22890
22902
  break;
22891
22903
  default:
@@ -25563,7 +25575,15 @@ class Interpretador extends interpretador_base_1.InterpretadorBase {
25563
25575
  const alvoTipoDe = await this.avaliar(valorTipoDe);
25564
25576
  return `tipo de<${alvoTipoDe}>`;
25565
25577
  case construtos_1.Variavel:
25566
- return valorTipoDe.tipo || (0, inferenciador_1.inferirTipoVariavel)(await this.avaliar(valorTipoDe));
25578
+ const tipoEstatico = valorTipoDe.tipo;
25579
+ if (tipoEstatico !== 'qualquer')
25580
+ return tipoEstatico;
25581
+ const valorAvaliado = await this.avaliar(valorTipoDe);
25582
+ const valorResolvido = this.resolverValor(valorAvaliado);
25583
+ if (valorResolvido === undefined || valorResolvido === null) {
25584
+ return 'qualquer';
25585
+ }
25586
+ return (0, inferenciador_1.inferirTipoVariavel)(valorResolvido);
25567
25587
  case construtos_1.Vetor:
25568
25588
  const vetor = valorTipoDe;
25569
25589
  const apenasValores = vetor.valores.filter((v) => !['ComentarioComoConstruto', 'Separador'].includes(v.constructor.name));