@designliquido/delegua 0.36.1 → 0.36.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/analisador-semantico/analisador-semantico-base.d.ts +69 -69
- package/analisador-semantico/analisador-semantico-base.js +180 -180
- package/analisador-semantico/analisador-semantico.d.ts +59 -59
- package/analisador-semantico/analisador-semantico.js +442 -442
- package/analisador-semantico/analisador-semantico.js.map +1 -1
- package/analisador-semantico/index.d.ts +3 -3
- package/analisador-semantico/index.js +19 -19
- package/analisador-semantico/pilha-variaveis.d.ts +20 -20
- package/analisador-semantico/pilha-variaveis.js +25 -25
- package/avaliador-sintatico/avaliador-sintatico-base.d.ts +69 -69
- package/avaliador-sintatico/avaliador-sintatico-base.js +223 -223
- package/avaliador-sintatico/avaliador-sintatico-base.js.map +1 -1
- package/avaliador-sintatico/avaliador-sintatico.d.ts +126 -126
- package/avaliador-sintatico/avaliador-sintatico.js +1093 -1093
- package/avaliador-sintatico/avaliador-sintatico.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-egua-classico.d.ts +73 -73
- package/avaliador-sintatico/dialetos/avaliador-sintatico-egua-classico.js +648 -648
- package/avaliador-sintatico/dialetos/avaliador-sintatico-egua-classico.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-guarani.d.ts +21 -21
- package/avaliador-sintatico/dialetos/avaliador-sintatico-guarani.js +149 -149
- package/avaliador-sintatico/dialetos/avaliador-sintatico-guarani.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.d.ts +87 -87
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js +770 -770
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-ipt.d.ts +34 -34
- package/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-ipt.js +168 -168
- package/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-ipt.js.map +1 -1
- package/avaliador-sintatico/dialetos/index.d.ts +3 -3
- package/avaliador-sintatico/dialetos/index.js +19 -19
- package/avaliador-sintatico/erro-avaliador-sintatico.d.ts +5 -5
- package/avaliador-sintatico/erro-avaliador-sintatico.js +11 -11
- package/avaliador-sintatico/index.d.ts +6 -6
- package/avaliador-sintatico/index.js +22 -22
- package/avaliador-sintatico/micro-avaliador-sintatico-base.d.ts +27 -27
- package/avaliador-sintatico/micro-avaliador-sintatico-base.js +116 -116
- package/avaliador-sintatico/micro-avaliador-sintatico-base.js.map +1 -1
- package/avaliador-sintatico/micro-avaliador-sintatico.d.ts +33 -33
- package/avaliador-sintatico/micro-avaliador-sintatico.js +287 -287
- package/avaliador-sintatico/micro-avaliador-sintatico.js.map +1 -1
- package/avaliador-sintatico/retornos/index.d.ts +3 -3
- package/avaliador-sintatico/retornos/index.js +19 -19
- package/avaliador-sintatico/retornos/retorno-declaracao.d.ts +3 -3
- package/avaliador-sintatico/retornos/retorno-declaracao.js +2 -2
- package/avaliador-sintatico/retornos/retorno-primario.d.ts +3 -3
- package/avaliador-sintatico/retornos/retorno-primario.js +2 -2
- package/avaliador-sintatico/retornos/retorno-resolver-declaracao.d.ts +2 -2
- package/avaliador-sintatico/retornos/retorno-resolver-declaracao.js +2 -2
- package/avaliador-sintatico/traducao/avaliador-sintatico-javascript.d.ts +59 -59
- package/avaliador-sintatico/traducao/avaliador-sintatico-javascript.js +150 -150
- package/bibliotecas/biblioteca-global.d.ts +157 -157
- package/bibliotecas/biblioteca-global.js +497 -498
- package/bibliotecas/biblioteca-global.js.map +1 -1
- package/bibliotecas/dialetos/egua-classico/biblioteca-global.d.ts +1 -1
- package/bibliotecas/dialetos/egua-classico/biblioteca-global.js +236 -236
- package/bibliotecas/dialetos/egua-classico/biblioteca-global.js.map +1 -1
- package/bibliotecas/dialetos/egua-classico/index.d.ts +2 -2
- package/bibliotecas/dialetos/egua-classico/index.js +32 -32
- package/bibliotecas/dialetos/egua-classico/index.js.map +1 -1
- package/bibliotecas/dialetos/egua-classico/matematica.d.ts +1 -1
- package/bibliotecas/dialetos/egua-classico/matematica.js +541 -541
- package/bibliotecas/dialetos/egua-classico/matematica.js.map +1 -1
- package/bibliotecas/dialetos/egua-classico/tempo.d.ts +1 -1
- package/bibliotecas/dialetos/egua-classico/tempo.js +39 -39
- package/bibliotecas/dialetos/egua-classico/tempo.js.map +1 -1
- package/bibliotecas/dialetos/egua-classico/textos.d.ts +8 -8
- package/bibliotecas/dialetos/egua-classico/textos.js +201 -201
- package/bibliotecas/dialetos/egua-classico/textos.js.map +1 -1
- package/bibliotecas/primitivas-dicionario.d.ts +6 -6
- package/bibliotecas/primitivas-dicionario.d.ts.map +1 -1
- package/bibliotecas/primitivas-dicionario.js +10 -10
- package/bibliotecas/primitivas-numero.d.ts +6 -6
- package/bibliotecas/primitivas-numero.d.ts.map +1 -1
- package/bibliotecas/primitivas-numero.js +10 -10
- package/bibliotecas/primitivas-texto.d.ts +17 -17
- package/bibliotecas/primitivas-texto.d.ts.map +1 -1
- package/bibliotecas/primitivas-texto.js +22 -22
- package/bibliotecas/primitivas-texto.js.map +1 -1
- package/bibliotecas/primitivas-vetor.d.ts +21 -21
- package/bibliotecas/primitivas-vetor.d.ts.map +1 -1
- package/bibliotecas/primitivas-vetor.js +90 -90
- package/bibliotecas/primitivas-vetor.js.map +1 -1
- package/bin/package.json +5 -4
- package/construtos/acesso-elemento-matriz.d.ts +12 -12
- package/construtos/acesso-elemento-matriz.js +17 -17
- package/construtos/acesso-indice-variavel.d.ts +15 -15
- package/construtos/acesso-indice-variavel.js +20 -20
- package/construtos/acesso-metodo-ou-propriedade.d.ts +14 -14
- package/construtos/acesso-metodo-ou-propriedade.js +19 -19
- package/construtos/agrupamento.d.ts +14 -14
- package/construtos/agrupamento.js +19 -19
- package/construtos/atribuicao-por-indice.d.ts +11 -11
- package/construtos/atribuicao-por-indice.js +16 -16
- package/construtos/atribuicao-por-indices-matriz.d.ts +12 -12
- package/construtos/atribuicao-por-indices-matriz.js +17 -17
- package/construtos/atribuir.d.ts +15 -15
- package/construtos/atribuir.js +24 -24
- package/construtos/atribuir.js.map +1 -1
- package/construtos/binario.d.ts +33 -33
- package/construtos/binario.js +38 -38
- package/construtos/chamada.d.ts +15 -15
- package/construtos/chamada.js +21 -21
- package/construtos/comentario.d.ts +15 -15
- package/construtos/comentario.js +20 -20
- package/construtos/constante.d.ts +12 -12
- package/construtos/constante.js +17 -17
- package/construtos/construto.d.ts +7 -7
- package/construtos/construto.js +2 -2
- package/construtos/decorador.d.ts +14 -14
- package/construtos/decorador.js +19 -19
- package/construtos/definir-valor.d.ts +11 -11
- package/construtos/definir-valor.js +16 -16
- package/construtos/dicionario.d.ts +10 -10
- package/construtos/dicionario.js +15 -15
- package/construtos/expressao-regular.d.ts +10 -10
- package/construtos/expressao-regular.js +15 -15
- package/construtos/fim-para.d.ts +22 -22
- package/construtos/fim-para.js +25 -25
- package/construtos/formatacao-escrita.d.ts +16 -16
- package/construtos/formatacao-escrita.js +21 -21
- package/construtos/funcao.d.ts +12 -12
- package/construtos/funcao.js +16 -16
- package/construtos/index.d.ts +29 -29
- package/construtos/index.js +45 -45
- package/construtos/isto.d.ts +9 -9
- package/construtos/isto.js +14 -14
- package/construtos/literal.d.ts +10 -10
- package/construtos/literal.js +14 -14
- package/construtos/logico.d.ts +11 -11
- package/construtos/logico.js +16 -16
- package/construtos/qual-tipo.d.ts +11 -11
- package/construtos/qual-tipo.js +16 -16
- package/construtos/super.d.ts +10 -10
- package/construtos/super.js +15 -15
- package/construtos/tipo-de.d.ts +10 -10
- package/construtos/tipo-de.js +15 -15
- package/construtos/tuplas/deceto.d.ts +18 -18
- package/construtos/tuplas/deceto.js +32 -32
- package/construtos/tuplas/dupla.d.ts +6 -6
- package/construtos/tuplas/dupla.js +12 -12
- package/construtos/tuplas/index.d.ts +13 -13
- package/construtos/tuplas/index.js +67 -67
- package/construtos/tuplas/index.js.map +1 -1
- package/construtos/tuplas/noneto.d.ts +15 -15
- package/construtos/tuplas/noneto.js +25 -25
- package/construtos/tuplas/octeto.d.ts +14 -14
- package/construtos/tuplas/octeto.js +24 -24
- package/construtos/tuplas/quarteto.d.ts +8 -8
- package/construtos/tuplas/quarteto.js +14 -14
- package/construtos/tuplas/quinteto.d.ts +9 -9
- package/construtos/tuplas/quinteto.js +15 -15
- package/construtos/tuplas/septeto.d.ts +13 -13
- package/construtos/tuplas/septeto.js +23 -23
- package/construtos/tuplas/sexteto.d.ts +10 -10
- package/construtos/tuplas/sexteto.js +16 -16
- package/construtos/tuplas/trio.d.ts +7 -7
- package/construtos/tuplas/trio.js +13 -13
- package/construtos/tuplas/tupla.d.ts +8 -8
- package/construtos/tuplas/tupla.js +9 -9
- package/construtos/unario.d.ts +11 -11
- package/construtos/unario.js +16 -16
- package/construtos/variavel.d.ts +9 -9
- package/construtos/variavel.js +14 -14
- package/construtos/vetor.d.ts +11 -11
- package/construtos/vetor.js +21 -21
- package/construtos/vetor.js.map +1 -1
- package/declaracoes/aleatorio.d.ts +15 -15
- package/declaracoes/aleatorio.js +15 -15
- package/declaracoes/bloco.d.ts +7 -7
- package/declaracoes/bloco.js +14 -14
- package/declaracoes/cabecalho-programa.d.ts +7 -7
- package/declaracoes/cabecalho-programa.js +14 -14
- package/declaracoes/classe.d.ts +14 -14
- package/declaracoes/classe.js +18 -18
- package/declaracoes/const-multiplo.d.ts +14 -14
- package/declaracoes/const-multiplo.js +19 -19
- package/declaracoes/const.d.ts +14 -14
- package/declaracoes/const.js +19 -19
- package/declaracoes/continua.d.ts +6 -6
- package/declaracoes/continua.js +13 -13
- package/declaracoes/declaracao.d.ts +8 -8
- package/declaracoes/declaracao.js +17 -17
- package/declaracoes/enquanto.d.ts +10 -10
- package/declaracoes/enquanto.js +15 -15
- package/declaracoes/escolha.d.ts +14 -14
- package/declaracoes/escolha.js +19 -19
- package/declaracoes/escreva-mesma-linha.d.ts +8 -8
- package/declaracoes/escreva-mesma-linha.js +14 -14
- package/declaracoes/escreva.d.ts +8 -8
- package/declaracoes/escreva.js +14 -14
- package/declaracoes/expressao.d.ts +8 -8
- package/declaracoes/expressao.js +14 -14
- package/declaracoes/falhar.d.ts +8 -8
- package/declaracoes/falhar.js +15 -15
- package/declaracoes/fazer.d.ts +10 -10
- package/declaracoes/fazer.js +15 -15
- package/declaracoes/funcao.d.ts +11 -11
- package/declaracoes/funcao.js +17 -17
- package/declaracoes/importar.d.ts +9 -9
- package/declaracoes/importar.js +15 -15
- package/declaracoes/index.d.ts +31 -31
- package/declaracoes/index.js +47 -47
- package/declaracoes/inicio-algoritmo.d.ts +6 -6
- package/declaracoes/inicio-algoritmo.js +13 -13
- package/declaracoes/leia-multiplo.d.ts +14 -14
- package/declaracoes/leia-multiplo.js +21 -21
- package/declaracoes/leia.d.ts +17 -17
- package/declaracoes/leia.js +21 -21
- package/declaracoes/para-cada.d.ts +11 -11
- package/declaracoes/para-cada.js +17 -17
- package/declaracoes/para.d.ts +19 -19
- package/declaracoes/para.js +24 -24
- package/declaracoes/propriedade-classe.d.ts +10 -10
- package/declaracoes/propriedade-classe.js +16 -16
- package/declaracoes/retorna.d.ts +8 -8
- package/declaracoes/retorna.js +15 -15
- package/declaracoes/se.d.ts +11 -11
- package/declaracoes/se.js +17 -17
- package/declaracoes/sustar.d.ts +6 -6
- package/declaracoes/sustar.js +13 -13
- package/declaracoes/tendo-como.d.ts +16 -16
- package/declaracoes/tendo-como.js +21 -21
- package/declaracoes/tente.d.ts +14 -14
- package/declaracoes/tente.js +20 -20
- package/declaracoes/var-multiplo.d.ts +15 -15
- package/declaracoes/var-multiplo.js +20 -20
- package/declaracoes/var.d.ts +16 -16
- package/declaracoes/var.js +21 -21
- package/depuracao/cyrb53.d.ts +9 -9
- package/depuracao/cyrb53.js +22 -22
- package/depuracao/cyrb53.js.map +1 -1
- package/depuracao/index.d.ts +2 -2
- package/depuracao/index.js +23 -23
- package/depuracao/ponto-parada.d.ts +4 -4
- package/depuracao/ponto-parada.js +2 -2
- package/espaco-variaveis.d.ts +19 -19
- package/espaco-variaveis.js +19 -19
- package/estruturas/chamavel.d.ts +7 -7
- package/estruturas/chamavel.js +12 -12
- package/estruturas/classe-padrao.d.ts +31 -31
- package/estruturas/classe-padrao.js +39 -39
- package/estruturas/delegua-funcao.d.ts +29 -29
- package/estruturas/delegua-funcao.js +141 -141
- package/estruturas/delegua-funcao.js.map +1 -1
- package/estruturas/descritor-tipo-classe.d.ts +37 -37
- package/estruturas/descritor-tipo-classe.js +79 -79
- package/estruturas/descritor-tipo-classe.js.map +1 -1
- package/estruturas/funcao-padrao.d.ts +23 -23
- package/estruturas/funcao-padrao.js +34 -34
- package/estruturas/index.d.ts +9 -9
- package/estruturas/index.js +25 -25
- package/estruturas/metodo-primitiva.d.ts +28 -28
- package/estruturas/metodo-primitiva.js +40 -40
- package/estruturas/modulo.d.ts +18 -18
- package/estruturas/modulo.js +24 -24
- package/estruturas/objeto-delegua-classe.d.ts +26 -26
- package/estruturas/objeto-delegua-classe.js +53 -53
- package/estruturas/objeto-delegua-classe.js.map +1 -1
- package/estruturas/objeto-padrao.d.ts +18 -18
- package/estruturas/objeto-padrao.js +32 -32
- package/estruturas/objeto-padrao.js.map +1 -1
- package/excecoes/erro-em-tempo-de-execucao.d.ts +7 -7
- package/excecoes/erro-em-tempo-de-execucao.js +13 -13
- package/excecoes/index.d.ts +1 -1
- package/excecoes/index.js +17 -17
- package/formatadores/formatador-delegua.d.ts +79 -79
- package/formatadores/formatador-delegua.js +676 -676
- package/formatadores/formatador-delegua.js.map +1 -1
- package/formatadores/index.d.ts +1 -1
- package/formatadores/index.js +17 -17
- package/geracao-identificadores/index.d.ts +1 -1
- package/geracao-identificadores/index.js +22 -23
- package/geracao-identificadores/index.js.map +1 -1
- package/index.d.ts +9 -9
- package/index.js +27 -27
- package/interfaces/analisador-semantico-interface.d.ts +6 -6
- package/interfaces/analisador-semantico-interface.js +2 -2
- package/interfaces/avaliador-sintatico-interface.d.ts +55 -55
- package/interfaces/avaliador-sintatico-interface.js +2 -2
- package/interfaces/construtos/index.d.ts +4 -4
- package/interfaces/construtos/index.js +2 -2
- package/interfaces/erros/diagnostico-analisador-semantico.d.ts +14 -14
- package/interfaces/erros/diagnostico-analisador-semantico.js +10 -10
- package/interfaces/erros/diagnostico-analisador-semantico.js.map +1 -1
- package/interfaces/erros/erro-interpretador.d.ts +8 -8
- package/interfaces/erros/erro-interpretador.js +2 -2
- package/interfaces/erros/index.d.ts +1 -1
- package/interfaces/erros/index.js +17 -17
- package/interfaces/escopo-execucao.d.ts +12 -12
- package/interfaces/escopo-execucao.js +2 -2
- package/interfaces/formatador-comum-interface.d.ts +11 -11
- package/interfaces/formatador-comum-interface.js +2 -2
- package/interfaces/funcao-hipotetica-interface.d.ts +3 -3
- package/interfaces/funcao-hipotetica-interface.js +2 -2
- package/interfaces/index.d.ts +16 -16
- package/interfaces/index.js +32 -32
- package/interfaces/interpretador-com-depuracao-interface.d.ts +17 -17
- package/interfaces/interpretador-com-depuracao-interface.js +2 -2
- package/interfaces/interpretador-interface-potigol.d.ts +5 -5
- package/interfaces/interpretador-interface-potigol.js +2 -2
- package/interfaces/interpretador-interface.d.ts +20 -20
- package/interfaces/interpretador-interface.js +2 -2
- package/interfaces/lexador-interface.d.ts +23 -23
- package/interfaces/lexador-interface.js +2 -2
- package/interfaces/parametro-interface.d.ts +15 -15
- package/interfaces/parametro-interface.js +2 -2
- package/interfaces/pilha-escopos-execucao-interface.d.ts +26 -26
- package/interfaces/pilha-escopos-execucao-interface.js +2 -2
- package/interfaces/pilha-interface.d.ts +7 -7
- package/interfaces/pilha-interface.js +2 -2
- package/interfaces/resolvedor-interface.d.ts +41 -41
- package/interfaces/resolvedor-interface.js +2 -2
- package/interfaces/retornos/index.d.ts +4 -4
- package/interfaces/retornos/index.js +20 -20
- package/interfaces/retornos/retorno-analisador-semantico.d.ts +4 -4
- package/interfaces/retornos/retorno-analisador-semantico.js +2 -2
- package/interfaces/retornos/retorno-avaliador-sintatico.d.ts +5 -5
- package/interfaces/retornos/retorno-avaliador-sintatico.js +2 -2
- package/interfaces/retornos/retorno-execucao-interface.d.ts +5 -5
- package/interfaces/retornos/retorno-execucao-interface.js +2 -2
- package/interfaces/retornos/retorno-interpretador.d.ts +5 -5
- package/interfaces/retornos/retorno-interpretador.js +2 -2
- package/interfaces/retornos/retorno-lexador.d.ts +9 -9
- package/interfaces/retornos/retorno-lexador.js +2 -2
- package/interfaces/simbolo-interface.d.ts +7 -7
- package/interfaces/simbolo-interface.js +2 -2
- package/interfaces/tradutor-interface.d.ts +3 -3
- package/interfaces/tradutor-interface.js +2 -2
- package/interfaces/variavel-hipotetica-interface.d.ts +8 -8
- package/interfaces/variavel-hipotetica-interface.js +2 -2
- package/interfaces/variavel-interface.d.ts +8 -8
- package/interfaces/variavel-interface.js +2 -2
- package/interfaces/visitante-comum-interface.d.ts +58 -58
- package/interfaces/visitante-comum-interface.js +2 -2
- package/interpretador/argumento-interface.d.ts +4 -4
- package/interpretador/argumento-interface.js +2 -2
- package/interpretador/comum.d.ts +2 -2
- package/interpretador/comum.js +51 -52
- package/interpretador/comum.js.map +1 -1
- package/interpretador/dialetos/egua-classico/index.d.ts +1 -1
- package/interpretador/dialetos/egua-classico/index.js +17 -17
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.d.ts +119 -119
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.js +815 -815
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.js.map +1 -1
- package/interpretador/dialetos/egua-classico/resolvedor/erro-resolvedor.d.ts +5 -5
- package/interpretador/dialetos/egua-classico/resolvedor/erro-resolvedor.js +11 -11
- package/interpretador/dialetos/egua-classico/resolvedor/index.d.ts +3 -3
- package/interpretador/dialetos/egua-classico/resolvedor/index.js +19 -19
- package/interpretador/dialetos/egua-classico/resolvedor/pilha-escopos.d.ts +9 -9
- package/interpretador/dialetos/egua-classico/resolvedor/pilha-escopos.js +25 -25
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.d.ts +106 -106
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js +441 -441
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js.map +1 -1
- package/interpretador/dialetos/egua-classico/resolvedor/retorno-resolvedor.d.ts +6 -6
- package/interpretador/dialetos/egua-classico/resolvedor/retorno-resolvedor.js +2 -2
- package/interpretador/dialetos/index.d.ts +2 -2
- package/interpretador/dialetos/index.js +18 -18
- package/interpretador/dialetos/portugol-ipt/index.d.ts +1 -1
- package/interpretador/dialetos/portugol-ipt/index.js +17 -17
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.d.ts +133 -133
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.js +501 -501
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.js.map +1 -1
- package/interpretador/index.d.ts +3 -3
- package/interpretador/index.js +19 -19
- package/interpretador/inferenciador.d.ts +15 -15
- package/interpretador/inferenciador.d.ts.map +1 -1
- package/interpretador/inferenciador.js +80 -80
- package/interpretador/inferenciador.js.map +1 -1
- package/interpretador/interpretador-base.d.ts +268 -268
- package/interpretador/interpretador-base.js +1399 -1399
- package/interpretador/interpretador-base.js.map +1 -1
- package/interpretador/interpretador-com-depuracao.d.ts +190 -190
- package/interpretador/interpretador-com-depuracao.js +568 -568
- package/interpretador/interpretador-com-depuracao.js.map +1 -1
- package/interpretador/pilha-escopos-execucao.d.ts +39 -39
- package/interpretador/pilha-escopos-execucao.js +243 -243
- package/interpretador/pilha-escopos-execucao.js.map +1 -1
- package/lexador/dialetos/index.d.ts +4 -4
- package/lexador/dialetos/index.js +20 -20
- package/lexador/dialetos/lexador-egua-classico.d.ts +36 -36
- package/lexador/dialetos/lexador-egua-classico.js +286 -286
- package/lexador/dialetos/lexador-egua-classico.js.map +1 -1
- package/lexador/dialetos/lexador-guarani.d.ts +10 -10
- package/lexador/dialetos/lexador-guarani.js +113 -113
- package/lexador/dialetos/lexador-guarani.js.map +1 -1
- package/lexador/dialetos/lexador-pitugues.d.ts +51 -51
- package/lexador/dialetos/lexador-pitugues.js +398 -398
- package/lexador/dialetos/lexador-pitugues.js.map +1 -1
- package/lexador/dialetos/lexador-portugol-ipt.d.ts +33 -33
- package/lexador/dialetos/lexador-portugol-ipt.js +237 -237
- package/lexador/dialetos/lexador-portugol-ipt.js.map +1 -1
- package/lexador/dialetos/palavras-reservadas/egua-classico.d.ts +32 -32
- package/lexador/dialetos/palavras-reservadas/egua-classico.js +39 -39
- package/lexador/dialetos/palavras-reservadas/guarani.d.ts +3 -3
- package/lexador/dialetos/palavras-reservadas/guarani.js +10 -10
- package/lexador/dialetos/palavras-reservadas/portugol-ipt.d.ts +13 -13
- package/lexador/dialetos/palavras-reservadas/portugol-ipt.js +20 -20
- package/lexador/dialetos/palavras-reservadas/rantiaquin.d.ts +1 -1
- package/lexador/dialetos/palavras-reservadas/rantiaquin.js +4 -4
- package/lexador/dialetos/pragma.d.ts +8 -8
- package/lexador/dialetos/pragma.js +2 -2
- package/lexador/erro-lexador.d.ts +5 -5
- package/lexador/erro-lexador.js +2 -2
- package/lexador/index.d.ts +4 -4
- package/lexador/index.js +20 -20
- package/lexador/lexador-base-linha-unica.d.ts +28 -28
- package/lexador/lexador-base-linha-unica.js +82 -82
- package/lexador/lexador-base-linha-unica.js.map +1 -1
- package/lexador/lexador-base.d.ts +41 -41
- package/lexador/lexador-base.js +112 -112
- package/lexador/lexador-base.js.map +1 -1
- package/lexador/lexador.d.ts +43 -43
- package/lexador/lexador.js +440 -440
- package/lexador/lexador.js.map +1 -1
- package/lexador/micro-lexador.d.ts +29 -29
- package/lexador/micro-lexador.js +207 -207
- package/lexador/micro-lexador.js.map +1 -1
- package/lexador/palavras-reservadas.d.ts +54 -54
- package/lexador/palavras-reservadas.js +61 -61
- package/lexador/simbolo.d.ts +10 -10
- package/lexador/simbolo.js +16 -16
- package/lexador/traducao/lexador-javascript.d.ts +28 -28
- package/lexador/traducao/lexador-javascript.js +58 -58
- package/package.json +5 -4
- package/quebras/index.d.ts +10 -10
- package/quebras/index.js +19 -19
- package/tipo-dados-elementar.d.ts +1 -1
- package/tipo-dados-elementar.js +2 -2
- package/tipos-de-dados/delegua.d.ts +18 -18
- package/tipos-de-dados/delegua.js +19 -19
- package/tipos-de-dados/listas-delegua.d.ts +6 -6
- package/tipos-de-dados/listas-delegua.js +7 -7
- package/tipos-de-dados/listas-primitivos.d.ts +5 -5
- package/tipos-de-dados/listas-primitivos.js +6 -6
- package/tipos-de-dados/primitivos.d.ts +16 -16
- package/tipos-de-dados/primitivos.js +17 -17
- package/tipos-de-simbolos/comum.d.ts +23 -23
- package/tipos-de-simbolos/comum.js +24 -24
- package/tipos-de-simbolos/delegua.d.ts +91 -91
- package/tipos-de-simbolos/delegua.js +92 -92
- package/tipos-de-simbolos/egua-classico.d.ts +75 -75
- package/tipos-de-simbolos/egua-classico.js +76 -76
- package/tipos-de-simbolos/guarani.d.ts +14 -14
- package/tipos-de-simbolos/guarani.js +15 -15
- package/tipos-de-simbolos/guarani.js.map +1 -1
- package/tipos-de-simbolos/microgramaticas/delegua.d.ts +46 -46
- package/tipos-de-simbolos/microgramaticas/delegua.js +47 -47
- package/tipos-de-simbolos/pitugues.d.ts +75 -75
- package/tipos-de-simbolos/pitugues.js +76 -76
- package/tipos-de-simbolos/portugol-ipt.d.ts +36 -36
- package/tipos-de-simbolos/portugol-ipt.js +37 -37
- package/tipos-de-simbolos/rantiaquin.d.ts +2 -2
- package/tipos-de-simbolos/rantiaquin.js +3 -3
- package/tradutores/dicionarios/dicionario-delegua-javascript.d.ts +2 -2
- package/tradutores/dicionarios/dicionario-delegua-javascript.js +10 -10
- package/tradutores/dicionarios/index.d.ts +1 -1
- package/tradutores/dicionarios/index.js +17 -17
- package/tradutores/index.d.ts +6 -6
- package/tradutores/index.js +22 -22
- package/tradutores/python/python3-lexer.d.ts +152 -152
- package/tradutores/python/python3-lexer.js +1227 -1227
- package/tradutores/python/python3-lexer.js.map +1 -1
- package/tradutores/python/python3-listener.d.ts +964 -964
- package/tradutores/python/python3-listener.js +3 -3
- package/tradutores/python/python3-parser.d.ts +1342 -1342
- package/tradutores/python/python3-parser.js +11226 -11226
- package/tradutores/python/python3-parser.js.map +1 -1
- package/tradutores/python/python3-visitor.d.ts +619 -619
- package/tradutores/python/python3-visitor.js +3 -3
- package/tradutores/tradutor-assembly-x64.d.ts +19 -19
- package/tradutores/tradutor-assembly-x64.js +128 -128
- package/tradutores/tradutor-assembly-x64.js.map +1 -1
- package/tradutores/tradutor-assemblyscript.d.ts +91 -91
- package/tradutores/tradutor-assemblyscript.js +590 -590
- package/tradutores/tradutor-assemblyscript.js.map +1 -1
- package/tradutores/tradutor-javascript.d.ts +95 -95
- package/tradutores/tradutor-javascript.js +577 -577
- package/tradutores/tradutor-javascript.js.map +1 -1
- package/tradutores/tradutor-portugol-ipt.d.ts +21 -21
- package/tradutores/tradutor-portugol-ipt.js +60 -60
- package/tradutores/tradutor-portugol-ipt.js.map +1 -1
- package/tradutores/tradutor-python.d.ts +65 -65
- package/tradutores/tradutor-python.js +461 -461
- package/tradutores/tradutor-python.js.map +1 -1
- package/tradutores/tradutor-reverso-javascript.d.ts +50 -50
- package/tradutores/tradutor-reverso-javascript.js +392 -392
- package/tradutores/tradutor-reverso-javascript.js.map +1 -1
- package/tradutores/tradutor-reverso-python.d.ts +32 -32
- package/tradutores/tradutor-reverso-python.js +71 -71
- package/tradutores/tradutor-reverso-python.js.map +1 -1
- package/umd/delegua.js +26337 -26340
|
@@ -1,1400 +1,1400 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.InterpretadorBase = void 0;
|
|
7
|
-
const browser_process_hrtime_1 = __importDefault(require("browser-process-hrtime"));
|
|
8
|
-
const estruturas_1 = require("../estruturas");
|
|
9
|
-
const construtos_1 = require("../construtos");
|
|
10
|
-
const pilha_escopos_execucao_1 = require("./pilha-escopos-execucao");
|
|
11
|
-
const quebras_1 = require("../quebras");
|
|
12
|
-
const inferenciador_1 = require("./inferenciador");
|
|
13
|
-
const metodo_primitiva_1 = require("../estruturas/metodo-primitiva");
|
|
14
|
-
const lexador_1 = require("../lexador");
|
|
15
|
-
const avaliador_sintatico_1 = require("../avaliador-sintatico");
|
|
16
|
-
const espaco_variaveis_1 = require("../espaco-variaveis");
|
|
17
|
-
const comum_1 = require("./comum");
|
|
18
|
-
const excecoes_1 = require("../excecoes");
|
|
19
|
-
const primitivas_dicionario_1 = __importDefault(require("../bibliotecas/primitivas-dicionario"));
|
|
20
|
-
const primitivas_numero_1 = __importDefault(require("../bibliotecas/primitivas-numero"));
|
|
21
|
-
const primitivas_texto_1 = __importDefault(require("../bibliotecas/primitivas-texto"));
|
|
22
|
-
const primitivas_vetor_1 = __importDefault(require("../bibliotecas/primitivas-vetor"));
|
|
23
|
-
const delegua_1 = __importDefault(require("../tipos-de-simbolos/delegua"));
|
|
24
|
-
const primitivos_1 = __importDefault(require("../tipos-de-dados/primitivos"));
|
|
25
|
-
const delegua_2 = __importDefault(require("../tipos-de-dados/delegua"));
|
|
26
|
-
/**
|
|
27
|
-
* O Interpretador visita todos os elementos complexos gerados pelo avaliador sintático (_parser_),
|
|
28
|
-
* e de fato executa a lógica de programação descrita no código.
|
|
29
|
-
*
|
|
30
|
-
* O Interpretador Base não contém dependências com o Node.js. É
|
|
31
|
-
* recomendado para uso em execuções que ocorrem no navegador de internet.
|
|
32
|
-
*/
|
|
33
|
-
class InterpretadorBase {
|
|
34
|
-
constructor(diretorioBase, performance = false, funcaoDeRetorno = null, funcaoDeRetornoMesmaLinha = null) {
|
|
35
|
-
this.resultadoInterpretador = [];
|
|
36
|
-
this.funcaoDeRetorno = null;
|
|
37
|
-
this.funcaoDeRetornoMesmaLinha = null;
|
|
38
|
-
this.interfaceDeEntrada = null; // Originalmente é `readline.Interface`
|
|
39
|
-
this.interfaceEntradaSaida = null;
|
|
40
|
-
this.emDeclaracaoTente = false;
|
|
41
|
-
this.microLexador = new lexador_1.MicroLexador();
|
|
42
|
-
this.microAvaliadorSintatico = new avaliador_sintatico_1.MicroAvaliadorSintatico();
|
|
43
|
-
this.regexInterpolacao = /\${(.*?)}/g;
|
|
44
|
-
this.tiposNumericos = [
|
|
45
|
-
delegua_2.default.INTEIRO,
|
|
46
|
-
delegua_2.default.NUMERO,
|
|
47
|
-
delegua_2.default.NÚMERO,
|
|
48
|
-
delegua_2.default.REAL
|
|
49
|
-
];
|
|
50
|
-
this.diretorioBase = diretorioBase;
|
|
51
|
-
this.performance = performance;
|
|
52
|
-
this.funcaoDeRetorno = funcaoDeRetorno || console.log;
|
|
53
|
-
this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout);
|
|
54
|
-
this.erros = [];
|
|
55
|
-
this.declaracoes = [];
|
|
56
|
-
this.resultadoInterpretador = [];
|
|
57
|
-
// Isso existe por causa de Potigol.
|
|
58
|
-
// Para acessar uma variável de classe, não é preciso a palavra `isto`.
|
|
59
|
-
this.expandirPropriedadesDeObjetosEmEspacoVariaveis = false;
|
|
60
|
-
// Por padrão é verdadeiro porque Delégua e Pituguês usam
|
|
61
|
-
// o interpretador base como implementação padrão.
|
|
62
|
-
this.requerDeclaracaoPropriedades = true;
|
|
63
|
-
this.pilhaEscoposExecucao = new pilha_escopos_execucao_1.PilhaEscoposExecucao();
|
|
64
|
-
const escopoExecucao = {
|
|
65
|
-
declaracoes: [],
|
|
66
|
-
declaracaoAtual: 0,
|
|
67
|
-
ambiente: new espaco_variaveis_1.EspacoVariaveis(),
|
|
68
|
-
finalizado: false,
|
|
69
|
-
tipo: 'outro',
|
|
70
|
-
emLacoRepeticao: false,
|
|
71
|
-
};
|
|
72
|
-
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
73
|
-
(0, comum_1.carregarBibliotecasGlobais)(this.pilhaEscoposExecucao);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Construtos de comentários não têm utilidade para o Interpretador.
|
|
77
|
-
* Apenas retornamos `Promise.resolve()` para não termos erros.
|
|
78
|
-
* @param declaracao A declaração de comentário.
|
|
79
|
-
*/
|
|
80
|
-
visitarDeclaracaoComentario(declaracao) {
|
|
81
|
-
return Promise.resolve();
|
|
82
|
-
}
|
|
83
|
-
async visitarDeclaracaoTendoComo(declaracao) {
|
|
84
|
-
const retornoInicializacao = await this.avaliar(declaracao.inicializacaoVariavel);
|
|
85
|
-
this.pilhaEscoposExecucao.definirConstante(declaracao.simboloVariavel.lexema, retornoInicializacao);
|
|
86
|
-
await this.executar(declaracao.corpo);
|
|
87
|
-
if (retornoInicializacao instanceof estruturas_1.ObjetoDeleguaClasse) {
|
|
88
|
-
const metodoFinalizar = retornoInicializacao.classe.metodos['finalizar'];
|
|
89
|
-
if (metodoFinalizar) {
|
|
90
|
-
const chamavel = metodoFinalizar.funcaoPorMetodoDeClasse(retornoInicializacao);
|
|
91
|
-
chamavel.chamar(this, []);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
async visitarDeclaracaoInicioAlgoritmo(declaracao) {
|
|
97
|
-
throw new Error('Método não implementado.');
|
|
98
|
-
}
|
|
99
|
-
async visitarDeclaracaoCabecalhoPrograma(declaracao) {
|
|
100
|
-
throw new Error('Método não implementado.');
|
|
101
|
-
}
|
|
102
|
-
async visitarExpressaoTupla(expressao) {
|
|
103
|
-
const chaves = Object.keys(expressao);
|
|
104
|
-
const valores = [];
|
|
105
|
-
for (let chave of chaves) {
|
|
106
|
-
const valor = await this.avaliar(expressao[chave]);
|
|
107
|
-
valores.push(valor);
|
|
108
|
-
}
|
|
109
|
-
return valores;
|
|
110
|
-
}
|
|
111
|
-
async visitarExpressaoAtribuicaoPorIndicesMatriz(expressao) {
|
|
112
|
-
throw new Error('Método não implementado.');
|
|
113
|
-
}
|
|
114
|
-
async visitarExpressaoAcessoElementoMatriz(expressao) {
|
|
115
|
-
throw new Error('Método não implementado.');
|
|
116
|
-
}
|
|
117
|
-
textoParaRegex(texto) {
|
|
118
|
-
const match = texto.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/);
|
|
119
|
-
return match
|
|
120
|
-
? new RegExp(match[2], match[3]
|
|
121
|
-
.split('')
|
|
122
|
-
.filter((char, pos, flagArr) => flagArr.indexOf(char) === pos)
|
|
123
|
-
.join(''))
|
|
124
|
-
: new RegExp(texto);
|
|
125
|
-
}
|
|
126
|
-
visitarExpressaoExpressaoRegular(expressao) {
|
|
127
|
-
return Promise.resolve(this.textoParaRegex(expressao.valor));
|
|
128
|
-
}
|
|
129
|
-
async visitarExpressaoTipoDe(expressao) {
|
|
130
|
-
let tipoDe = expressao.valor;
|
|
131
|
-
if (tipoDe instanceof construtos_1.Agrupamento ||
|
|
132
|
-
tipoDe instanceof construtos_1.Binario ||
|
|
133
|
-
tipoDe instanceof construtos_1.Chamada ||
|
|
134
|
-
tipoDe instanceof construtos_1.Dicionario ||
|
|
135
|
-
tipoDe instanceof construtos_1.TipoDe ||
|
|
136
|
-
tipoDe instanceof construtos_1.Unario ||
|
|
137
|
-
tipoDe instanceof construtos_1.Variavel) {
|
|
138
|
-
tipoDe = await this.avaliar(tipoDe);
|
|
139
|
-
return tipoDe.tipo || (0, inferenciador_1.inferirTipoVariavel)(tipoDe);
|
|
140
|
-
}
|
|
141
|
-
return (0, inferenciador_1.inferirTipoVariavel)((tipoDe === null || tipoDe === void 0 ? void 0 : tipoDe.valores) || tipoDe);
|
|
142
|
-
}
|
|
143
|
-
// TODO: Depreciado. Priorizar `visitarExpressaoTipoDe`.
|
|
144
|
-
async visitarExpressaoQualTipo(expressao) {
|
|
145
|
-
throw new Error('Método não implementado.');
|
|
146
|
-
}
|
|
147
|
-
async visitarExpressaoFalhar(expressao) {
|
|
148
|
-
var _a;
|
|
149
|
-
const textoFalha = (_a = expressao.explicacao.valor) !== null && _a !== void 0 ? _a : (await this.avaliar(expressao.explicacao)).valor;
|
|
150
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, textoFalha, expressao.linha);
|
|
151
|
-
}
|
|
152
|
-
async visitarExpressaoFimPara(declaracao) {
|
|
153
|
-
throw new Error('Método não implementado.');
|
|
154
|
-
}
|
|
155
|
-
async avaliar(expressao) {
|
|
156
|
-
// Descomente o código abaixo quando precisar detectar expressões undefined ou nulas.
|
|
157
|
-
// Por algum motivo o depurador do VSCode não funciona direito aqui
|
|
158
|
-
// com breakpoint condicional.
|
|
159
|
-
/* if (expressao === null || expressao === undefined) {
|
|
160
|
-
console.log('Aqui');
|
|
161
|
-
} */
|
|
162
|
-
return await expressao.aceitar(this);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Execução da leitura de valores da entrada configurada no
|
|
166
|
-
* início da aplicação.
|
|
167
|
-
* @param expressao Expressão do tipo Leia
|
|
168
|
-
* @returns Promise com o resultado da leitura.
|
|
169
|
-
*/
|
|
170
|
-
async visitarExpressaoLeia(expressao) {
|
|
171
|
-
const mensagem = expressao.argumentos && expressao.argumentos[0] ? expressao.argumentos[0].valor : '> ';
|
|
172
|
-
return new Promise((resolucao) => this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
173
|
-
resolucao(resposta);
|
|
174
|
-
}));
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Execução da leitura de valores da entrada configurada no
|
|
178
|
-
* início da aplicação.
|
|
179
|
-
* @param expressao Expressão do tipo `LeiaMultiplo`.
|
|
180
|
-
* @returns Promise com o resultado da leitura.
|
|
181
|
-
*/
|
|
182
|
-
async visitarExpressaoLeiaMultiplo(expressao) {
|
|
183
|
-
const mensagem = '> ';
|
|
184
|
-
if (expressao.argumento instanceof construtos_1.Literal) {
|
|
185
|
-
let valor = expressao.argumento.valor;
|
|
186
|
-
if (typeof valor === primitivos_1.default.TEXTO) {
|
|
187
|
-
return new Promise((resolucao) => this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
188
|
-
resolucao(String(resposta)
|
|
189
|
-
.split(valor)
|
|
190
|
-
.filter((r) => !/(\s+)/.test(r)));
|
|
191
|
-
}));
|
|
192
|
-
}
|
|
193
|
-
let respostas = [];
|
|
194
|
-
for (let i = 0; i < valor; i++) {
|
|
195
|
-
this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
196
|
-
respostas.push(resposta);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
return Promise.resolve(respostas);
|
|
200
|
-
}
|
|
201
|
-
return Promise.resolve();
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Retira a interpolação de um texto.
|
|
205
|
-
* @param {texto} texto O texto
|
|
206
|
-
* @param {any[]} variaveis A lista de variaveis interpoladas
|
|
207
|
-
* @returns O texto com o valor das variaveis.
|
|
208
|
-
*/
|
|
209
|
-
retirarInterpolacao(texto, variaveis) {
|
|
210
|
-
let textoFinal = texto;
|
|
211
|
-
variaveis.forEach((elemento) => {
|
|
212
|
-
var _a, _b, _c;
|
|
213
|
-
if (((_a = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _a === void 0 ? void 0 : _a.tipo) === delegua_2.default.LOGICO) {
|
|
214
|
-
textoFinal = textoFinal.replace('${' + elemento.variavel + '}', this.paraTexto((_b = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _b === void 0 ? void 0 : _b.valor));
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
const valor = ((_c = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _c === void 0 ? void 0 : _c.hasOwnProperty('valor')) ? elemento === null || elemento === void 0 ? void 0 : elemento.valor.valor : elemento === null || elemento === void 0 ? void 0 : elemento.valor;
|
|
218
|
-
textoFinal = textoFinal.replace('${' + elemento.variavel + '}', `${this.paraTexto(valor)}`);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
return textoFinal;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Resolve todas as interpolações em um texto.
|
|
225
|
-
* @param {texto} textoOriginal O texto original com as variáveis interpoladas.
|
|
226
|
-
* @returns Uma lista de variáveis interpoladas.
|
|
227
|
-
*/
|
|
228
|
-
async resolverInterpolacoes(textoOriginal, linha) {
|
|
229
|
-
const variaveis = textoOriginal.match(this.regexInterpolacao);
|
|
230
|
-
let resultadosAvaliacaoSintatica = variaveis.map((s) => {
|
|
231
|
-
const nomeVariavel = s.replace(/[\$\{\}]*/gm, '');
|
|
232
|
-
let microLexador = this.microLexador.mapear(nomeVariavel);
|
|
233
|
-
const resultadoMicroAvaliadorSintatico = this.microAvaliadorSintatico.analisar(microLexador, linha);
|
|
234
|
-
return {
|
|
235
|
-
nomeVariavel,
|
|
236
|
-
resultadoMicroAvaliadorSintatico,
|
|
237
|
-
};
|
|
238
|
-
});
|
|
239
|
-
// TODO: Verificar erros do `resultadosAvaliacaoSintatica`.
|
|
240
|
-
const resolucoesPromises = await Promise.all(resultadosAvaliacaoSintatica
|
|
241
|
-
.flatMap((r) => r.resultadoMicroAvaliadorSintatico.declaracoes)
|
|
242
|
-
.map((d) => this.avaliar(d)));
|
|
243
|
-
return resolucoesPromises.map((item, indice) => ({
|
|
244
|
-
variavel: resultadosAvaliacaoSintatica[indice].nomeVariavel,
|
|
245
|
-
valor: item,
|
|
246
|
-
}));
|
|
247
|
-
}
|
|
248
|
-
async visitarExpressaoLiteral(expressao) {
|
|
249
|
-
if (this.regexInterpolacao.test(expressao.valor)) {
|
|
250
|
-
const variaveis = await this.resolverInterpolacoes(expressao.valor, expressao.linha);
|
|
251
|
-
return this.retirarInterpolacao(expressao.valor, variaveis);
|
|
252
|
-
}
|
|
253
|
-
return expressao.valor;
|
|
254
|
-
}
|
|
255
|
-
async visitarExpressaoAgrupamento(expressao) {
|
|
256
|
-
return await this.avaliar(expressao.expressao);
|
|
257
|
-
}
|
|
258
|
-
eVerdadeiro(objeto) {
|
|
259
|
-
if (objeto === null)
|
|
260
|
-
return false;
|
|
261
|
-
if (typeof objeto === primitivos_1.default.BOOLEANO)
|
|
262
|
-
return Boolean(objeto);
|
|
263
|
-
if (objeto.hasOwnProperty('valor')) {
|
|
264
|
-
return Boolean(objeto.valor);
|
|
265
|
-
}
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
verificarOperandoNumero(operador, operando) {
|
|
269
|
-
if (typeof operando === primitivos_1.default.NUMERO || operando.tipo === delegua_2.default.NUMERO)
|
|
270
|
-
return;
|
|
271
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(operador, 'Operando precisa ser um número.', Number(operador.linha));
|
|
272
|
-
}
|
|
273
|
-
async visitarExpressaoUnaria(expressao) {
|
|
274
|
-
const operando = await this.avaliar(expressao.operando);
|
|
275
|
-
let valor = operando.hasOwnProperty('valor') ? operando.valor : operando;
|
|
276
|
-
switch (expressao.operador.tipo) {
|
|
277
|
-
case delegua_1.default.SUBTRACAO:
|
|
278
|
-
this.verificarOperandoNumero(expressao.operador, valor);
|
|
279
|
-
return -valor;
|
|
280
|
-
case delegua_1.default.NEGACAO:
|
|
281
|
-
return !this.eVerdadeiro(valor);
|
|
282
|
-
case delegua_1.default.BIT_NOT:
|
|
283
|
-
return ~valor;
|
|
284
|
-
// Para incrementar e decrementar, primeiro precisamos saber se o operador
|
|
285
|
-
// veio antes do literal ou variável.
|
|
286
|
-
// Se veio antes e o operando é uma variável, precisamos incrementar/decrementar,
|
|
287
|
-
// armazenar o valor da variável pra só então devolver o valor.
|
|
288
|
-
case delegua_1.default.INCREMENTAR:
|
|
289
|
-
if (expressao.incidenciaOperador === 'ANTES') {
|
|
290
|
-
valor++;
|
|
291
|
-
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
292
|
-
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, valor);
|
|
293
|
-
}
|
|
294
|
-
return valor;
|
|
295
|
-
}
|
|
296
|
-
const valorAnteriorIncremento = valor;
|
|
297
|
-
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, ++valor);
|
|
298
|
-
return valorAnteriorIncremento;
|
|
299
|
-
case delegua_1.default.DECREMENTAR:
|
|
300
|
-
if (expressao.incidenciaOperador === 'ANTES') {
|
|
301
|
-
valor--;
|
|
302
|
-
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
303
|
-
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, valor);
|
|
304
|
-
}
|
|
305
|
-
return valor;
|
|
306
|
-
}
|
|
307
|
-
const valorAnteriorDecremento = valor;
|
|
308
|
-
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, --valor);
|
|
309
|
-
return valorAnteriorDecremento;
|
|
310
|
-
}
|
|
311
|
-
return null;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Formata uma saída de acordo com o número e espaços e casas decimais solicitados.
|
|
315
|
-
* @param declaracao A declaração de formatação de escrita.
|
|
316
|
-
* @returns {string} A saída formatada como texto e os respectivos parâmetros aplicados.
|
|
317
|
-
*/
|
|
318
|
-
async visitarExpressaoFormatacaoEscrita(declaracao) {
|
|
319
|
-
let resultado = '';
|
|
320
|
-
const conteudo = await this.avaliar(declaracao.expressao);
|
|
321
|
-
const valorConteudo = (conteudo === null || conteudo === void 0 ? void 0 : conteudo.hasOwnProperty('valor')) ? conteudo.valor : conteudo;
|
|
322
|
-
const tipoConteudo = conteudo.hasOwnProperty('tipo') ? conteudo.tipo : typeof conteudo;
|
|
323
|
-
resultado = valorConteudo;
|
|
324
|
-
if ([delegua_2.default.NUMERO, primitivos_1.default.NUMERO].includes(tipoConteudo) &&
|
|
325
|
-
declaracao.casasDecimais > 0) {
|
|
326
|
-
resultado = valorConteudo.toLocaleString('pt', { maximumFractionDigits: declaracao.casasDecimais });
|
|
327
|
-
}
|
|
328
|
-
if (declaracao.espacos > 0) {
|
|
329
|
-
resultado += ' '.repeat(declaracao.espacos);
|
|
330
|
-
}
|
|
331
|
-
return resultado;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Lógica para verificação de valores iguais, para Delégua e alguns dialetos.
|
|
335
|
-
* @param esquerda Uma variável.
|
|
336
|
-
* @param direita Outra variável.
|
|
337
|
-
* @returns Verdadeiro se são iguais. Falso em caso contrário.
|
|
338
|
-
*/
|
|
339
|
-
eIgual(esquerda, direita) {
|
|
340
|
-
if (esquerda === null && direita === null)
|
|
341
|
-
return true;
|
|
342
|
-
if (esquerda === null)
|
|
343
|
-
return false;
|
|
344
|
-
return esquerda === direita;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Verifica se operandos são números, que podem ser tanto variáveis puras do JavaScript
|
|
348
|
-
* (neste caso, `number`), ou podem ser variáveis de Delégua com inferência (`VariavelInterface`).
|
|
349
|
-
* @param operador O símbolo do operador.
|
|
350
|
-
* @param direita O operando direito.
|
|
351
|
-
* @param esquerda O operando esquerdo.
|
|
352
|
-
* @returns Se ambos os operandos são números ou não.
|
|
353
|
-
*/
|
|
354
|
-
verificarOperandosNumeros(operador, direita, esquerda) {
|
|
355
|
-
const tipoDireita = direita.tipo
|
|
356
|
-
? direita.tipo
|
|
357
|
-
: typeof direita === primitivos_1.default.NUMERO
|
|
358
|
-
? delegua_2.default.NUMERO
|
|
359
|
-
: String(NaN);
|
|
360
|
-
const tipoEsquerda = esquerda.tipo
|
|
361
|
-
? esquerda.tipo
|
|
362
|
-
: typeof esquerda === primitivos_1.default.NUMERO
|
|
363
|
-
? delegua_2.default.NUMERO
|
|
364
|
-
: String(NaN);
|
|
365
|
-
if (this.tiposNumericos.includes(tipoDireita) && this.tiposNumericos.includes(tipoEsquerda))
|
|
366
|
-
return;
|
|
367
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(operador, 'Operadores precisam ser números.', operador.linha);
|
|
368
|
-
}
|
|
369
|
-
async visitarExpressaoBinaria(expressao) {
|
|
370
|
-
const esquerda = await this.avaliar(expressao.esquerda);
|
|
371
|
-
const direita = await this.avaliar(expressao.direita);
|
|
372
|
-
const valorEsquerdo = (esquerda === null || esquerda === void 0 ? void 0 : esquerda.hasOwnProperty('valor')) ? esquerda.valor : esquerda;
|
|
373
|
-
const valorDireito = (direita === null || direita === void 0 ? void 0 : direita.hasOwnProperty('valor')) ? direita.valor : direita;
|
|
374
|
-
const tipoEsquerdo = (esquerda === null || esquerda === void 0 ? void 0 : esquerda.hasOwnProperty('tipo')) ? esquerda.tipo : (0, inferenciador_1.inferirTipoVariavel)(esquerda);
|
|
375
|
-
const tipoDireito = (direita === null || direita === void 0 ? void 0 : direita.hasOwnProperty('tipo')) ? direita.tipo : (0, inferenciador_1.inferirTipoVariavel)(direita);
|
|
376
|
-
switch (expressao.operador.tipo) {
|
|
377
|
-
case delegua_1.default.EXPONENCIACAO:
|
|
378
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
379
|
-
return Math.pow(valorEsquerdo, valorDireito);
|
|
380
|
-
case delegua_1.default.MAIOR:
|
|
381
|
-
if (this.tiposNumericos.includes(tipoEsquerdo) && this.tiposNumericos.includes(tipoDireito)) {
|
|
382
|
-
return Number(valorEsquerdo) > Number(valorDireito);
|
|
383
|
-
}
|
|
384
|
-
return String(valorEsquerdo) > String(valorDireito);
|
|
385
|
-
case delegua_1.default.MAIOR_IGUAL:
|
|
386
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
387
|
-
return Number(valorEsquerdo) >= Number(valorDireito);
|
|
388
|
-
case delegua_1.default.MENOR:
|
|
389
|
-
if (this.tiposNumericos.includes(tipoEsquerdo) && this.tiposNumericos.includes(tipoDireito)) {
|
|
390
|
-
return Number(valorEsquerdo) < Number(valorDireito);
|
|
391
|
-
}
|
|
392
|
-
return String(valorEsquerdo) < String(valorDireito);
|
|
393
|
-
case delegua_1.default.MENOR_IGUAL:
|
|
394
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
395
|
-
return Number(valorEsquerdo) <= Number(valorDireito);
|
|
396
|
-
case delegua_1.default.SUBTRACAO:
|
|
397
|
-
case delegua_1.default.MENOS_IGUAL:
|
|
398
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
399
|
-
return Number(valorEsquerdo) - Number(valorDireito);
|
|
400
|
-
case delegua_1.default.ADICAO:
|
|
401
|
-
case delegua_1.default.MAIS_IGUAL:
|
|
402
|
-
if (this.tiposNumericos.includes(tipoEsquerdo) &&
|
|
403
|
-
this.tiposNumericos.includes(tipoDireito)) {
|
|
404
|
-
return Number(valorEsquerdo) + Number(valorDireito);
|
|
405
|
-
}
|
|
406
|
-
return this.paraTexto(valorEsquerdo) + this.paraTexto(valorDireito);
|
|
407
|
-
case delegua_1.default.DIVISAO:
|
|
408
|
-
case delegua_1.default.DIVISAO_IGUAL:
|
|
409
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
410
|
-
return Number(valorEsquerdo) / Number(valorDireito);
|
|
411
|
-
case delegua_1.default.DIVISAO_INTEIRA:
|
|
412
|
-
case delegua_1.default.DIVISAO_INTEIRA_IGUAL:
|
|
413
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
414
|
-
return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
|
|
415
|
-
case delegua_1.default.MULTIPLICACAO:
|
|
416
|
-
case delegua_1.default.MULTIPLICACAO_IGUAL:
|
|
417
|
-
if (tipoEsquerdo === delegua_2.default.TEXTO || tipoDireito === delegua_2.default.TEXTO) {
|
|
418
|
-
// Sem ambos os valores resolvem como texto, multiplica normal.
|
|
419
|
-
// Se apenas um resolve como texto, o outro repete o
|
|
420
|
-
// texto n vezes, sendo n o valor do outro.
|
|
421
|
-
if (tipoEsquerdo === delegua_2.default.TEXTO && tipoDireito === delegua_2.default.TEXTO) {
|
|
422
|
-
return Number(valorEsquerdo) * Number(valorDireito);
|
|
423
|
-
}
|
|
424
|
-
if (tipoEsquerdo === delegua_2.default.TEXTO) {
|
|
425
|
-
return valorEsquerdo.repeat(Number(valorDireito));
|
|
426
|
-
}
|
|
427
|
-
return valorDireito.repeat(Number(valorEsquerdo));
|
|
428
|
-
}
|
|
429
|
-
return Number(valorEsquerdo) * Number(valorDireito);
|
|
430
|
-
case delegua_1.default.MODULO:
|
|
431
|
-
case delegua_1.default.MODULO_IGUAL:
|
|
432
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
433
|
-
return Number(valorEsquerdo) % Number(valorDireito);
|
|
434
|
-
case delegua_1.default.BIT_AND:
|
|
435
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
436
|
-
return Number(valorEsquerdo) & Number(valorDireito);
|
|
437
|
-
case delegua_1.default.BIT_XOR:
|
|
438
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
439
|
-
return Number(valorEsquerdo) ^ Number(valorDireito);
|
|
440
|
-
case delegua_1.default.BIT_OR:
|
|
441
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
442
|
-
return Number(valorEsquerdo) | Number(valorDireito);
|
|
443
|
-
case delegua_1.default.MENOR_MENOR:
|
|
444
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
445
|
-
return Number(valorEsquerdo) << Number(valorDireito);
|
|
446
|
-
case delegua_1.default.MAIOR_MAIOR:
|
|
447
|
-
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
448
|
-
return Number(valorEsquerdo) >> Number(valorDireito);
|
|
449
|
-
case delegua_1.default.DIFERENTE:
|
|
450
|
-
return !this.eIgual(valorEsquerdo, valorDireito);
|
|
451
|
-
case delegua_1.default.IGUAL_IGUAL:
|
|
452
|
-
return this.eIgual(valorEsquerdo, valorDireito);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Faz a chamada do método de uma primitiva (por exemplo, número, texto, etc.) com seus
|
|
457
|
-
* respectivos argumentos.
|
|
458
|
-
* @param {Chamada} expressao A expressão de chamada.
|
|
459
|
-
* @param {MetodoPrimitiva} entidadeChamada O método da primitiva chamado.
|
|
460
|
-
* @returns O resultado da chamada do método da primitiva.
|
|
461
|
-
*/
|
|
462
|
-
async chamarMetodoPrimitiva(expressao, entidadeChamada) {
|
|
463
|
-
const argumentosResolvidos = [];
|
|
464
|
-
for (const argumento of expressao.argumentos) {
|
|
465
|
-
const valorResolvido = await this.avaliar(argumento);
|
|
466
|
-
argumentosResolvidos.push((valorResolvido === null || valorResolvido === void 0 ? void 0 : valorResolvido.hasOwnProperty('valor')) ? valorResolvido.valor : valorResolvido);
|
|
467
|
-
}
|
|
468
|
-
return await entidadeChamada.chamar(this, argumentosResolvidos);
|
|
469
|
-
}
|
|
470
|
-
async resolverArgumentosChamada(expressao) {
|
|
471
|
-
const argumentos = [];
|
|
472
|
-
for (let i = 0; i < expressao.argumentos.length; i++) {
|
|
473
|
-
const variavelArgumento = expressao.argumentos[i];
|
|
474
|
-
const nomeArgumento = variavelArgumento.hasOwnProperty('simbolo')
|
|
475
|
-
? variavelArgumento.simbolo.lexema
|
|
476
|
-
: undefined;
|
|
477
|
-
argumentos.push({
|
|
478
|
-
nome: nomeArgumento,
|
|
479
|
-
valor: await this.avaliar(variavelArgumento),
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
return argumentos;
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Resolve paraâmetros da chamada de acordo com o tipo da entidade chamada.
|
|
486
|
-
* @param {Chamavel} entidadeChamada A entidade chamada.
|
|
487
|
-
* @returns Os parâmetros resolvidos.
|
|
488
|
-
*/
|
|
489
|
-
resolverParametrosChamada(entidadeChamada) {
|
|
490
|
-
if (entidadeChamada instanceof estruturas_1.DeleguaFuncao) {
|
|
491
|
-
return entidadeChamada.declaracao.parametros;
|
|
492
|
-
}
|
|
493
|
-
if (entidadeChamada instanceof estruturas_1.DescritorTipoClasse) {
|
|
494
|
-
return entidadeChamada.metodos.construtor
|
|
495
|
-
? entidadeChamada.metodos.construtor.declaracao.parametros
|
|
496
|
-
: [];
|
|
497
|
-
}
|
|
498
|
-
return [];
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Executa uma chamada de função, método ou classe.
|
|
502
|
-
* @param expressao A expressão chamada.
|
|
503
|
-
* @returns O resultado da chamada.
|
|
504
|
-
*/
|
|
505
|
-
async visitarExpressaoDeChamada(expressao) {
|
|
506
|
-
try {
|
|
507
|
-
const variavelEntidadeChamada = await this.avaliar(expressao.entidadeChamada);
|
|
508
|
-
if (variavelEntidadeChamada === null) {
|
|
509
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Chamada de função ou método inexistente: ' + String(expressao.entidadeChamada), expressao.linha));
|
|
510
|
-
}
|
|
511
|
-
const entidadeChamada = variavelEntidadeChamada.hasOwnProperty('valor')
|
|
512
|
-
? variavelEntidadeChamada.valor
|
|
513
|
-
: variavelEntidadeChamada;
|
|
514
|
-
if (entidadeChamada instanceof estruturas_1.DeleguaModulo) {
|
|
515
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Entidade chamada é um módulo de Delégua. Provavelmente você quer chamar um de seus componentes?', expressao.linha));
|
|
516
|
-
}
|
|
517
|
-
if (entidadeChamada instanceof metodo_primitiva_1.MetodoPrimitiva) {
|
|
518
|
-
return await this.chamarMetodoPrimitiva(expressao, entidadeChamada);
|
|
519
|
-
}
|
|
520
|
-
const argumentos = await this.resolverArgumentosChamada(expressao);
|
|
521
|
-
// TODO: Aparentemente isso nunca é usado se o bloco de resolução de parâmetros,
|
|
522
|
-
// mais abaixo, também não é.
|
|
523
|
-
// Estudar remoção mais adiante.
|
|
524
|
-
const parametros = this.resolverParametrosChamada(entidadeChamada);
|
|
525
|
-
const aridade = entidadeChamada.aridade ? entidadeChamada.aridade() : entidadeChamada.length;
|
|
526
|
-
// Completar os parâmetros não preenchidos com nulos.
|
|
527
|
-
if (argumentos.length < aridade) {
|
|
528
|
-
const diferenca = aridade - argumentos.length;
|
|
529
|
-
for (let i = 0; i < diferenca; i++) {
|
|
530
|
-
argumentos.push(null);
|
|
531
|
-
}
|
|
532
|
-
} /* else {
|
|
533
|
-
// TODO: Aparentemente isso aqui nunca funcionou.
|
|
534
|
-
// Avaliar de simplesmente apagar este código, e usar o que foi
|
|
535
|
-
// implementado em `DeleguaFuncao.chamar`.
|
|
536
|
-
if (
|
|
537
|
-
parametros &&
|
|
538
|
-
parametros.length > 0 &&
|
|
539
|
-
parametros[parametros.length - 1].abrangencia === 'multiplo'
|
|
540
|
-
) {
|
|
541
|
-
let novosArgumentos = argumentos.slice(0, parametros.length - 1);
|
|
542
|
-
novosArgumentos = novosArgumentos.concat(
|
|
543
|
-
argumentos.slice(parametros.length - 1, argumentos.length)
|
|
544
|
-
);
|
|
545
|
-
argumentos = novosArgumentos;
|
|
546
|
-
}
|
|
547
|
-
} */
|
|
548
|
-
if (entidadeChamada instanceof estruturas_1.FuncaoPadrao) {
|
|
549
|
-
try {
|
|
550
|
-
return entidadeChamada.chamar(this, argumentos.map((a) => a && a.valor && a.valor.hasOwnProperty('valor') ? a.valor.valor : a === null || a === void 0 ? void 0 : a.valor), expressao.entidadeChamada.simbolo);
|
|
551
|
-
}
|
|
552
|
-
catch (erro) {
|
|
553
|
-
this.erros.push({
|
|
554
|
-
erroInterno: erro,
|
|
555
|
-
linha: expressao.linha,
|
|
556
|
-
hashArquivo: expressao.hashArquivo,
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
// Por algum motivo misterioso, `entidadeChamada instanceof Chamavel` dá `false` em Liquido,
|
|
561
|
-
// mesmo que esteja tudo certo com `DeleguaFuncao`,
|
|
562
|
-
// então precisamos testar o nome do construtor também.
|
|
563
|
-
if (entidadeChamada instanceof estruturas_1.Chamavel || entidadeChamada.constructor.name === 'DeleguaFuncao') {
|
|
564
|
-
const retornoEntidadeChamada = await entidadeChamada.chamar(this, argumentos);
|
|
565
|
-
return retornoEntidadeChamada;
|
|
566
|
-
}
|
|
567
|
-
// A função chamada pode ser de uma biblioteca JavaScript.
|
|
568
|
-
// Neste caso apenas testamos se o tipo é uma função.
|
|
569
|
-
// TODO: Descobrir qual caso exatamente passa aqui.
|
|
570
|
-
if (typeof entidadeChamada === primitivos_1.default.FUNCAO) {
|
|
571
|
-
let objeto = null;
|
|
572
|
-
if (expressao.entidadeChamada.objeto) {
|
|
573
|
-
objeto = await this.avaliar(expressao.entidadeChamada.objeto);
|
|
574
|
-
}
|
|
575
|
-
return entidadeChamada.apply(objeto.hasOwnProperty('valor') ? objeto.valor : objeto, argumentos);
|
|
576
|
-
}
|
|
577
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Só pode chamar função ou classe.', expressao.linha));
|
|
578
|
-
}
|
|
579
|
-
catch (erro) {
|
|
580
|
-
this.erros.push({
|
|
581
|
-
erroInterno: erro,
|
|
582
|
-
linha: expressao.linha,
|
|
583
|
-
hashArquivo: expressao.hashArquivo,
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Execução de uma expressão de atribuição.
|
|
589
|
-
* @param expressao A expressão.
|
|
590
|
-
* @returns O valor atribuído.
|
|
591
|
-
*/
|
|
592
|
-
async visitarExpressaoDeAtribuicao(expressao) {
|
|
593
|
-
const valor = await this.avaliar(expressao.valor);
|
|
594
|
-
const valorResolvido = valor !== undefined && valor.hasOwnProperty('valor') ? valor.valor : valor;
|
|
595
|
-
let indice = null;
|
|
596
|
-
if (expressao.indice) {
|
|
597
|
-
indice = await this.avaliar(expressao.indice);
|
|
598
|
-
}
|
|
599
|
-
this.pilhaEscoposExecucao.atribuirVariavel(expressao.simbolo, valorResolvido, indice);
|
|
600
|
-
return valorResolvido;
|
|
601
|
-
}
|
|
602
|
-
procurarVariavel(simbolo) {
|
|
603
|
-
return this.pilhaEscoposExecucao.obterValorVariavel(simbolo);
|
|
604
|
-
}
|
|
605
|
-
visitarExpressaoDeVariavel(expressao) {
|
|
606
|
-
return this.procurarVariavel(expressao.simbolo);
|
|
607
|
-
}
|
|
608
|
-
async visitarDeclaracaoDeExpressao(declaracao) {
|
|
609
|
-
return await this.avaliar(declaracao.expressao);
|
|
610
|
-
}
|
|
611
|
-
async visitarExpressaoLogica(expressao) {
|
|
612
|
-
const esquerda = await this.avaliar(expressao.esquerda);
|
|
613
|
-
if (expressao.operador.tipo === delegua_1.default.EM) {
|
|
614
|
-
const direita = await this.avaliar(expressao.direita);
|
|
615
|
-
if (Array.isArray(direita) || typeof direita === primitivos_1.default.TEXTO) {
|
|
616
|
-
return direita.includes(esquerda);
|
|
617
|
-
}
|
|
618
|
-
else if (direita.constructor === Object) {
|
|
619
|
-
return esquerda in direita;
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(esquerda, "Tipo de chamada inválida com 'em'.", expressao.linha);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
// se um estado for verdadeiro, retorna verdadeiro
|
|
626
|
-
if (expressao.operador.tipo === delegua_1.default.OU) {
|
|
627
|
-
if (this.eVerdadeiro(esquerda))
|
|
628
|
-
return esquerda;
|
|
629
|
-
}
|
|
630
|
-
// se um estado for falso, retorna falso
|
|
631
|
-
if (expressao.operador.tipo === delegua_1.default.E) {
|
|
632
|
-
if (!this.eVerdadeiro(esquerda))
|
|
633
|
-
return esquerda;
|
|
634
|
-
}
|
|
635
|
-
return await this.avaliar(expressao.direita);
|
|
636
|
-
}
|
|
637
|
-
async visitarDeclaracaoPara(declaracao) {
|
|
638
|
-
const declaracaoInicializador = Array.isArray(declaracao.inicializador)
|
|
639
|
-
? declaracao.inicializador[0]
|
|
640
|
-
: declaracao.inicializador;
|
|
641
|
-
if (declaracaoInicializador !== null) {
|
|
642
|
-
await this.avaliar(declaracaoInicializador);
|
|
643
|
-
}
|
|
644
|
-
let retornoExecucao;
|
|
645
|
-
while (!(retornoExecucao instanceof quebras_1.Quebra)) {
|
|
646
|
-
if (declaracao.condicao !== null && !this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
647
|
-
break;
|
|
648
|
-
}
|
|
649
|
-
try {
|
|
650
|
-
retornoExecucao = await this.executar(declaracao.corpo);
|
|
651
|
-
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
652
|
-
return null;
|
|
653
|
-
}
|
|
654
|
-
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
655
|
-
retornoExecucao = null;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
catch (erro) {
|
|
659
|
-
this.erros.push({
|
|
660
|
-
erroInterno: erro,
|
|
661
|
-
linha: declaracao.linha,
|
|
662
|
-
hashArquivo: declaracao.hashArquivo,
|
|
663
|
-
});
|
|
664
|
-
return Promise.reject(erro);
|
|
665
|
-
}
|
|
666
|
-
if (declaracao.incrementar !== null) {
|
|
667
|
-
await this.avaliar(declaracao.incrementar);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
return retornoExecucao;
|
|
671
|
-
}
|
|
672
|
-
async visitarDeclaracaoParaCada(declaracao) {
|
|
673
|
-
let retornoExecucao;
|
|
674
|
-
const vetorResolvido = await this.avaliar(declaracao.vetor);
|
|
675
|
-
const valorVetorResolvido = vetorResolvido.hasOwnProperty('valor') ? vetorResolvido.valor : vetorResolvido;
|
|
676
|
-
if (!Array.isArray(valorVetorResolvido)) {
|
|
677
|
-
return Promise.reject("Variável ou literal provida em instrução 'para cada' não é um vetor.");
|
|
678
|
-
}
|
|
679
|
-
while (!(retornoExecucao instanceof quebras_1.Quebra) && declaracao.posicaoAtual < valorVetorResolvido.length) {
|
|
680
|
-
try {
|
|
681
|
-
this.pilhaEscoposExecucao.definirVariavel(declaracao.nomeVariavelIteracao, valorVetorResolvido[declaracao.posicaoAtual]);
|
|
682
|
-
retornoExecucao = await this.executar(declaracao.corpo);
|
|
683
|
-
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
684
|
-
return null;
|
|
685
|
-
}
|
|
686
|
-
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
687
|
-
retornoExecucao = null;
|
|
688
|
-
}
|
|
689
|
-
declaracao.posicaoAtual++;
|
|
690
|
-
}
|
|
691
|
-
catch (erro) {
|
|
692
|
-
this.erros.push({
|
|
693
|
-
erroInterno: erro,
|
|
694
|
-
linha: declaracao.linha,
|
|
695
|
-
hashArquivo: declaracao.hashArquivo,
|
|
696
|
-
});
|
|
697
|
-
return Promise.reject(erro);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
return retornoExecucao;
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Executa uma expressão Se, que tem uma condição, pode ter um bloco
|
|
704
|
-
* Senão, e múltiplos blocos Senão-se.
|
|
705
|
-
* @param declaracao A declaração Se.
|
|
706
|
-
* @returns O resultado da avaliação do bloco cuja condição é verdadeira.
|
|
707
|
-
*/
|
|
708
|
-
async visitarDeclaracaoSe(declaracao) {
|
|
709
|
-
if (this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
710
|
-
return await this.executar(declaracao.caminhoEntao);
|
|
711
|
-
}
|
|
712
|
-
for (let i = 0; i < declaracao.caminhosSeSenao.length; i++) {
|
|
713
|
-
const atual = declaracao.caminhosSeSenao[i];
|
|
714
|
-
if (this.eVerdadeiro(await this.avaliar(atual.condicao))) {
|
|
715
|
-
return await this.executar(atual.caminho);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
if (declaracao.caminhoSenao !== null) {
|
|
719
|
-
return await this.executar(declaracao.caminhoSenao);
|
|
720
|
-
}
|
|
721
|
-
return null;
|
|
722
|
-
}
|
|
723
|
-
async visitarDeclaracaoEnquanto(declaracao) {
|
|
724
|
-
let retornoExecucao;
|
|
725
|
-
while (!(retornoExecucao instanceof quebras_1.Quebra) && this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
726
|
-
try {
|
|
727
|
-
retornoExecucao = await this.executar(declaracao.corpo);
|
|
728
|
-
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
729
|
-
return null;
|
|
730
|
-
}
|
|
731
|
-
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
732
|
-
retornoExecucao = null;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
catch (erro) {
|
|
736
|
-
this.erros.push({
|
|
737
|
-
erroInterno: erro,
|
|
738
|
-
linha: declaracao.linha,
|
|
739
|
-
hashArquivo: declaracao.hashArquivo,
|
|
740
|
-
});
|
|
741
|
-
return Promise.reject(erro);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
return retornoExecucao;
|
|
745
|
-
}
|
|
746
|
-
async visitarDeclaracaoEscolha(declaracao) {
|
|
747
|
-
const condicaoEscolha = await this.avaliar(declaracao.identificadorOuLiteral);
|
|
748
|
-
const valorCondicaoEscolha = condicaoEscolha.hasOwnProperty('valor') ? condicaoEscolha.valor : condicaoEscolha;
|
|
749
|
-
const caminhos = declaracao.caminhos;
|
|
750
|
-
const caminhoPadrao = declaracao.caminhoPadrao;
|
|
751
|
-
let encontrado = false;
|
|
752
|
-
try {
|
|
753
|
-
for (let i = 0; i < caminhos.length; i++) {
|
|
754
|
-
const caminho = caminhos[i];
|
|
755
|
-
for (let j = 0; j < caminho.condicoes.length; j++) {
|
|
756
|
-
const condicaoAvaliada = await this.avaliar(caminho.condicoes[j]);
|
|
757
|
-
if (condicaoAvaliada === valorCondicaoEscolha) {
|
|
758
|
-
encontrado = true;
|
|
759
|
-
try {
|
|
760
|
-
await this.executarBloco(caminho.declaracoes);
|
|
761
|
-
}
|
|
762
|
-
catch (erro) {
|
|
763
|
-
this.erros.push({
|
|
764
|
-
erroInterno: erro,
|
|
765
|
-
linha: declaracao.linha,
|
|
766
|
-
hashArquivo: declaracao.hashArquivo,
|
|
767
|
-
});
|
|
768
|
-
return Promise.reject(erro);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
if (caminhoPadrao !== null && !encontrado) {
|
|
774
|
-
await this.executarBloco(caminhoPadrao.declaracoes);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
catch (erro) {
|
|
778
|
-
this.erros.push({
|
|
779
|
-
erroInterno: erro,
|
|
780
|
-
linha: declaracao.linha,
|
|
781
|
-
hashArquivo: declaracao.hashArquivo,
|
|
782
|
-
});
|
|
783
|
-
throw erro;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
async visitarDeclaracaoFazer(declaracao) {
|
|
787
|
-
let retornoExecucao;
|
|
788
|
-
do {
|
|
789
|
-
try {
|
|
790
|
-
retornoExecucao = await this.executar(declaracao.caminhoFazer);
|
|
791
|
-
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
792
|
-
return null;
|
|
793
|
-
}
|
|
794
|
-
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
795
|
-
retornoExecucao = null;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
catch (erro) {
|
|
799
|
-
this.erros.push({
|
|
800
|
-
erroInterno: erro,
|
|
801
|
-
linha: declaracao.linha,
|
|
802
|
-
hashArquivo: declaracao.hashArquivo,
|
|
803
|
-
});
|
|
804
|
-
return Promise.reject(erro);
|
|
805
|
-
}
|
|
806
|
-
} while (!(retornoExecucao instanceof quebras_1.Quebra) &&
|
|
807
|
-
this.eVerdadeiro(await this.avaliar(declaracao.condicaoEnquanto)));
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* Interpretação de uma declaração `tente`.
|
|
811
|
-
* @param declaracao O objeto da declaração.
|
|
812
|
-
*/
|
|
813
|
-
async visitarDeclaracaoTente(declaracao) {
|
|
814
|
-
let valorRetorno;
|
|
815
|
-
try {
|
|
816
|
-
this.emDeclaracaoTente = true;
|
|
817
|
-
try {
|
|
818
|
-
valorRetorno = await this.executarBloco(declaracao.caminhoTente);
|
|
819
|
-
}
|
|
820
|
-
catch (erro) {
|
|
821
|
-
if (declaracao.caminhoPegue !== null) {
|
|
822
|
-
// `caminhoPegue` aqui pode ser um construto de função (se `pegue` tem parâmetros)
|
|
823
|
-
// ou um vetor de `Declaracao` (`pegue` sem parâmetros).
|
|
824
|
-
// As execuções, portanto, são diferentes.
|
|
825
|
-
if (Array.isArray(declaracao.caminhoPegue)) {
|
|
826
|
-
valorRetorno = await this.executarBloco(declaracao.caminhoPegue);
|
|
827
|
-
}
|
|
828
|
-
else {
|
|
829
|
-
const literalErro = new construtos_1.Literal(declaracao.hashArquivo, Number(declaracao.linha), erro.mensagem);
|
|
830
|
-
const chamadaPegue = new construtos_1.Chamada(declaracao.caminhoPegue.hashArquivo, declaracao.caminhoPegue, null, [literalErro]);
|
|
831
|
-
valorRetorno = await chamadaPegue.aceitar(this);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
finally {
|
|
837
|
-
if (declaracao.caminhoFinalmente !== null)
|
|
838
|
-
valorRetorno = await this.executarBloco(declaracao.caminhoFinalmente);
|
|
839
|
-
this.emDeclaracaoTente = false;
|
|
840
|
-
}
|
|
841
|
-
return valorRetorno;
|
|
842
|
-
}
|
|
843
|
-
async visitarDeclaracaoImportar(declaracao) {
|
|
844
|
-
return Promise.reject('Importação de arquivos não suportada por Interpretador Base.');
|
|
845
|
-
}
|
|
846
|
-
async avaliarArgumentosEscreva(argumentos) {
|
|
847
|
-
let formatoTexto = '';
|
|
848
|
-
for (const argumento of argumentos) {
|
|
849
|
-
const resultadoAvaliacao = await this.avaliar(argumento);
|
|
850
|
-
let valor = (resultadoAvaliacao === null || resultadoAvaliacao === void 0 ? void 0 : resultadoAvaliacao.hasOwnProperty('valor')) ? resultadoAvaliacao.valor : resultadoAvaliacao;
|
|
851
|
-
formatoTexto += `${this.paraTexto(valor)} `;
|
|
852
|
-
}
|
|
853
|
-
return formatoTexto.trimEnd();
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Execução de uma escrita na saída padrão, sem quebras de linha.
|
|
857
|
-
* Implementada para alguns dialetos, como VisuAlg.
|
|
858
|
-
* @param declaracao A declaração.
|
|
859
|
-
* @returns Sempre nulo, por convenção de visita.
|
|
860
|
-
*/
|
|
861
|
-
async visitarDeclaracaoEscrevaMesmaLinha(declaracao) {
|
|
862
|
-
try {
|
|
863
|
-
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
|
|
864
|
-
this.funcaoDeRetornoMesmaLinha(formatoTexto);
|
|
865
|
-
return null;
|
|
866
|
-
}
|
|
867
|
-
catch (erro) {
|
|
868
|
-
this.erros.push({
|
|
869
|
-
erroInterno: erro,
|
|
870
|
-
linha: declaracao.linha,
|
|
871
|
-
hashArquivo: declaracao.hashArquivo,
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
/**
|
|
876
|
-
* Execução de uma escrita na saída configurada, que pode ser `console` (padrão) ou
|
|
877
|
-
* alguma função para escrever numa página Web.
|
|
878
|
-
* @param declaracao A declaração.
|
|
879
|
-
* @returns Sempre nulo, por convenção de visita.
|
|
880
|
-
*/
|
|
881
|
-
async visitarDeclaracaoEscreva(declaracao) {
|
|
882
|
-
try {
|
|
883
|
-
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
|
|
884
|
-
this.funcaoDeRetorno(formatoTexto);
|
|
885
|
-
return null;
|
|
886
|
-
}
|
|
887
|
-
catch (erro) {
|
|
888
|
-
this.erros.push({
|
|
889
|
-
erroInterno: erro,
|
|
890
|
-
linha: declaracao.linha,
|
|
891
|
-
hashArquivo: declaracao.hashArquivo,
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Empilha declarações na pilha de escopos de execução, cria um novo ambiente e
|
|
897
|
-
* executa as declarações empilhadas.
|
|
898
|
-
* Se o retorno do último bloco foi uma exceção (normalmente um erro em tempo de execução),
|
|
899
|
-
* atira a exceção daqui.
|
|
900
|
-
* Isso é usado, por exemplo, em blocos tente ... pegue ... finalmente.
|
|
901
|
-
* @param declaracoes Um vetor de declaracoes a ser executado.
|
|
902
|
-
* @param ambiente O ambiente de execução quando houver, como parâmetros, argumentos, etc.
|
|
903
|
-
*/
|
|
904
|
-
async executarBloco(declaracoes, ambiente) {
|
|
905
|
-
const escopoExecucao = {
|
|
906
|
-
declaracoes: declaracoes,
|
|
907
|
-
declaracaoAtual: 0,
|
|
908
|
-
ambiente: ambiente || new espaco_variaveis_1.EspacoVariaveis(),
|
|
909
|
-
finalizado: false,
|
|
910
|
-
tipo: 'outro',
|
|
911
|
-
emLacoRepeticao: false,
|
|
912
|
-
};
|
|
913
|
-
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
914
|
-
const retornoUltimoEscopo = await this.executarUltimoEscopo();
|
|
915
|
-
if (retornoUltimoEscopo instanceof excecoes_1.ErroEmTempoDeExecucao) {
|
|
916
|
-
return Promise.reject(retornoUltimoEscopo);
|
|
917
|
-
}
|
|
918
|
-
return retornoUltimoEscopo;
|
|
919
|
-
}
|
|
920
|
-
async visitarExpressaoBloco(declaracao) {
|
|
921
|
-
return await this.executarBloco(declaracao.declaracoes);
|
|
922
|
-
}
|
|
923
|
-
async avaliacaoDeclaracaoVarOuConst(declaracao) {
|
|
924
|
-
let valorOuOutraVariavel = null;
|
|
925
|
-
if (declaracao.inicializador !== null) {
|
|
926
|
-
valorOuOutraVariavel = await this.avaliar(declaracao.inicializador);
|
|
927
|
-
}
|
|
928
|
-
let valorFinal = null;
|
|
929
|
-
if (valorOuOutraVariavel !== null && valorOuOutraVariavel !== undefined) {
|
|
930
|
-
valorFinal = valorOuOutraVariavel.hasOwnProperty('valor')
|
|
931
|
-
? valorOuOutraVariavel.valor
|
|
932
|
-
: valorOuOutraVariavel;
|
|
933
|
-
}
|
|
934
|
-
return valorFinal;
|
|
935
|
-
}
|
|
936
|
-
/**
|
|
937
|
-
* Executa expressão de definição de constante.
|
|
938
|
-
* @param declaracao A declaração `Const`.
|
|
939
|
-
* @returns Sempre retorna nulo.
|
|
940
|
-
*/
|
|
941
|
-
async visitarDeclaracaoConst(declaracao) {
|
|
942
|
-
const valorFinal = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
943
|
-
this.pilhaEscoposExecucao.definirConstante(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
|
|
944
|
-
return null;
|
|
945
|
-
}
|
|
946
|
-
/**
|
|
947
|
-
* Executa expressão de definição de múltiplas constantes.
|
|
948
|
-
* @param declaracao A declaração `ConstMultiplo`.
|
|
949
|
-
* @returns Sempre retorna nulo.
|
|
950
|
-
*/
|
|
951
|
-
async visitarDeclaracaoConstMultiplo(declaracao) {
|
|
952
|
-
const valoresFinais = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
953
|
-
for (let [indice, valor] of valoresFinais.entries()) {
|
|
954
|
-
this.pilhaEscoposExecucao.definirConstante(declaracao.simbolos[indice].lexema, valor, declaracao.tipo);
|
|
955
|
-
}
|
|
956
|
-
return null;
|
|
957
|
-
}
|
|
958
|
-
visitarExpressaoContinua(declaracao) {
|
|
959
|
-
return new quebras_1.ContinuarQuebra();
|
|
960
|
-
}
|
|
961
|
-
visitarExpressaoSustar(declaracao) {
|
|
962
|
-
return new quebras_1.SustarQuebra();
|
|
963
|
-
}
|
|
964
|
-
async visitarExpressaoRetornar(declaracao) {
|
|
965
|
-
let valor = null;
|
|
966
|
-
if (declaracao.valor != null)
|
|
967
|
-
valor = await this.avaliar(declaracao.valor);
|
|
968
|
-
return new quebras_1.RetornoQuebra(valor);
|
|
969
|
-
}
|
|
970
|
-
async visitarExpressaoDeleguaFuncao(corpoDeclaracao) {
|
|
971
|
-
return new estruturas_1.DeleguaFuncao(null, corpoDeclaracao);
|
|
972
|
-
}
|
|
973
|
-
async visitarExpressaoAtribuicaoPorIndice(expressao) {
|
|
974
|
-
const promises = await Promise.all([
|
|
975
|
-
this.avaliar(expressao.objeto),
|
|
976
|
-
this.avaliar(expressao.indice),
|
|
977
|
-
this.avaliar(expressao.valor),
|
|
978
|
-
]);
|
|
979
|
-
let objeto = promises[0];
|
|
980
|
-
let indice = promises[1];
|
|
981
|
-
const valor = promises[2];
|
|
982
|
-
if (objeto.tipo === delegua_2.default.TUPLA) {
|
|
983
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.objeto.simbolo.lexema, 'Não é possível modificar uma tupla. As tuplas são estruturas de dados imutáveis.', expressao.linha));
|
|
984
|
-
}
|
|
985
|
-
objeto = objeto.hasOwnProperty('valor') ? objeto.valor : objeto;
|
|
986
|
-
indice = indice.hasOwnProperty('valor') ? indice.valor : indice;
|
|
987
|
-
if (Array.isArray(objeto)) {
|
|
988
|
-
if (indice < 0 && objeto.length !== 0) {
|
|
989
|
-
while (indice < 0) {
|
|
990
|
-
indice += objeto.length;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
while (objeto.length < indice) {
|
|
994
|
-
objeto.push(null);
|
|
995
|
-
}
|
|
996
|
-
objeto[indice] = valor;
|
|
997
|
-
}
|
|
998
|
-
else if (objeto.constructor === Object ||
|
|
999
|
-
objeto instanceof estruturas_1.ObjetoDeleguaClasse ||
|
|
1000
|
-
objeto instanceof estruturas_1.DeleguaFuncao ||
|
|
1001
|
-
objeto instanceof estruturas_1.DescritorTipoClasse ||
|
|
1002
|
-
objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1003
|
-
objeto[indice] = valor;
|
|
1004
|
-
}
|
|
1005
|
-
else {
|
|
1006
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.objeto.nome, 'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.', expressao.linha));
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
async visitarExpressaoAcessoIndiceVariavel(expressao) {
|
|
1010
|
-
const promises = await Promise.all([this.avaliar(expressao.entidadeChamada), this.avaliar(expressao.indice)]);
|
|
1011
|
-
const variavelObjeto = promises[0];
|
|
1012
|
-
const indice = promises[1];
|
|
1013
|
-
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1014
|
-
let valorIndice = indice.hasOwnProperty('valor') ? indice.valor : indice;
|
|
1015
|
-
if (Array.isArray(objeto)) {
|
|
1016
|
-
if (!Number.isInteger(valorIndice)) {
|
|
1017
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Somente inteiros podem ser usados para indexar um vetor.', expressao.linha));
|
|
1018
|
-
}
|
|
1019
|
-
if (valorIndice < 0 && objeto.length !== 0) {
|
|
1020
|
-
while (valorIndice < 0) {
|
|
1021
|
-
valorIndice += objeto.length;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
if (valorIndice >= objeto.length) {
|
|
1025
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Índice do vetor fora do intervalo.', expressao.linha));
|
|
1026
|
-
}
|
|
1027
|
-
return objeto[valorIndice];
|
|
1028
|
-
}
|
|
1029
|
-
if (objeto instanceof construtos_1.Vetor) {
|
|
1030
|
-
return objeto.valores[valorIndice];
|
|
1031
|
-
}
|
|
1032
|
-
if (objeto.constructor === Object ||
|
|
1033
|
-
objeto instanceof estruturas_1.ObjetoDeleguaClasse ||
|
|
1034
|
-
objeto instanceof estruturas_1.DeleguaFuncao ||
|
|
1035
|
-
objeto instanceof estruturas_1.DescritorTipoClasse ||
|
|
1036
|
-
objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1037
|
-
return objeto[valorIndice] || null;
|
|
1038
|
-
}
|
|
1039
|
-
if (typeof objeto === primitivos_1.default.TEXTO) {
|
|
1040
|
-
if (!Number.isInteger(valorIndice)) {
|
|
1041
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Somente inteiros podem ser usados para indexar um vetor.', expressao.linha));
|
|
1042
|
-
}
|
|
1043
|
-
if (valorIndice < 0 && objeto.length !== 0) {
|
|
1044
|
-
while (valorIndice < 0) {
|
|
1045
|
-
valorIndice += objeto.length;
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
if (valorIndice >= objeto.length) {
|
|
1049
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Índice fora do tamanho.', expressao.linha));
|
|
1050
|
-
}
|
|
1051
|
-
return objeto.charAt(valorIndice);
|
|
1052
|
-
}
|
|
1053
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.entidadeChamada.nome, 'Somente listas, dicionários, classes e objetos podem ter seus valores indexados.', expressao.linha));
|
|
1054
|
-
}
|
|
1055
|
-
async visitarExpressaoDefinirValor(expressao) {
|
|
1056
|
-
const variavelObjeto = await this.avaliar(expressao.objeto);
|
|
1057
|
-
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1058
|
-
if (objeto.constructor.name !== 'ObjetoDeleguaClasse' && objeto.constructor !== Object) {
|
|
1059
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.nome, 'Somente instâncias e dicionários podem possuir campos.', expressao.linha));
|
|
1060
|
-
}
|
|
1061
|
-
const valor = await this.avaliar(expressao.valor);
|
|
1062
|
-
if (objeto.constructor.name === 'ObjetoDeleguaClasse') {
|
|
1063
|
-
objeto.definir(expressao.nome, valor);
|
|
1064
|
-
return valor;
|
|
1065
|
-
}
|
|
1066
|
-
if (objeto.constructor === Object) {
|
|
1067
|
-
objeto[expressao.nome.lexema] = valor;
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
visitarDeclaracaoDefinicaoFuncao(declaracao) {
|
|
1071
|
-
const funcao = new estruturas_1.DeleguaFuncao(declaracao.simbolo.lexema, declaracao.funcao);
|
|
1072
|
-
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, funcao);
|
|
1073
|
-
}
|
|
1074
|
-
/**
|
|
1075
|
-
* Executa uma declaração de classe.
|
|
1076
|
-
* Uma variável do tipo `DeleguaClasse` é adicionada à pilha de escopos de execução.
|
|
1077
|
-
* @param declaracao A declaração de classe.
|
|
1078
|
-
* @returns Sempre retorna nulo, por ser requerido pelo contrato de visita.
|
|
1079
|
-
*/
|
|
1080
|
-
async visitarDeclaracaoClasse(declaracao) {
|
|
1081
|
-
let superClasse = null;
|
|
1082
|
-
if (declaracao.superClasse !== null && declaracao.superClasse !== undefined) {
|
|
1083
|
-
const variavelSuperClasse = await this.avaliar(declaracao.superClasse);
|
|
1084
|
-
superClasse = variavelSuperClasse.valor;
|
|
1085
|
-
if (!(superClasse instanceof estruturas_1.DescritorTipoClasse)) {
|
|
1086
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(declaracao.superClasse.nome, 'Superclasse precisa ser uma classe.', declaracao.linha);
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
// TODO: Precisamos disso?
|
|
1090
|
-
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, declaracao);
|
|
1091
|
-
if (declaracao.superClasse !== null && declaracao.superClasse !== undefined) {
|
|
1092
|
-
this.pilhaEscoposExecucao.definirVariavel('super', superClasse);
|
|
1093
|
-
}
|
|
1094
|
-
const metodos = {};
|
|
1095
|
-
const definirMetodos = declaracao.metodos;
|
|
1096
|
-
for (let i = 0; i < declaracao.metodos.length; i++) {
|
|
1097
|
-
const metodoAtual = definirMetodos[i];
|
|
1098
|
-
const eInicializador = metodoAtual.simbolo.lexema === 'construtor';
|
|
1099
|
-
const funcao = new estruturas_1.DeleguaFuncao(metodoAtual.simbolo.lexema, metodoAtual.funcao, undefined, eInicializador);
|
|
1100
|
-
metodos[metodoAtual.simbolo.lexema] = funcao;
|
|
1101
|
-
}
|
|
1102
|
-
const descritorTipoClasse = new estruturas_1.DescritorTipoClasse(declaracao.simbolo, superClasse, metodos, declaracao.propriedades);
|
|
1103
|
-
descritorTipoClasse.dialetoRequerExpansaoPropriedadesEspacoVariaveis =
|
|
1104
|
-
this.expandirPropriedadesDeObjetosEmEspacoVariaveis;
|
|
1105
|
-
descritorTipoClasse.dialetoRequerDeclaracaoPropriedades = this.requerDeclaracaoPropriedades;
|
|
1106
|
-
// TODO: Recolocar isso se for necessário.
|
|
1107
|
-
/* if (superClasse !== null) {
|
|
1108
|
-
this.ambiente = this.ambiente.enclosing;
|
|
1109
|
-
} */
|
|
1110
|
-
this.pilhaEscoposExecucao.atribuirVariavel(declaracao.simbolo, descritorTipoClasse);
|
|
1111
|
-
return null;
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
* Executa um acesso a método, normalmente de um objeto de classe.
|
|
1115
|
-
* @param {AcessoMetodoOuPropriedade} expressao A expressão de acesso.
|
|
1116
|
-
* @returns O resultado da execução.
|
|
1117
|
-
*/
|
|
1118
|
-
async visitarExpressaoAcessoMetodo(expressao) {
|
|
1119
|
-
let variavelObjeto = await this.avaliar(expressao.objeto);
|
|
1120
|
-
// Este caso acontece quando há encadeamento de métodos.
|
|
1121
|
-
// Por exemplo, `objeto1.metodo1().metodo2()`.
|
|
1122
|
-
// Como `RetornoQuebra` também possui `valor`, precisamos extrair o
|
|
1123
|
-
// valor dele primeiro.
|
|
1124
|
-
if (variavelObjeto.constructor.name === 'RetornoQuebra') {
|
|
1125
|
-
variavelObjeto = variavelObjeto.valor;
|
|
1126
|
-
}
|
|
1127
|
-
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1128
|
-
// Outro caso que `instanceof` simplesmente não funciona para casos em Liquido,
|
|
1129
|
-
// então testamos também o nome do construtor.
|
|
1130
|
-
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto.constructor.name === 'ObjetoDeleguaClasse') {
|
|
1131
|
-
return objeto.obter(expressao.simbolo) || null;
|
|
1132
|
-
}
|
|
1133
|
-
// Objeto simples do JavaScript, ou dicionário de Delégua.
|
|
1134
|
-
if (objeto.constructor === Object) {
|
|
1135
|
-
const metodoDePrimitivaDicionario = primitivas_dicionario_1.default[expressao.simbolo.lexema];
|
|
1136
|
-
if (metodoDePrimitivaDicionario) {
|
|
1137
|
-
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaDicionario);
|
|
1138
|
-
}
|
|
1139
|
-
return objeto[expressao.simbolo.lexema] || null;
|
|
1140
|
-
}
|
|
1141
|
-
// Casos em que o objeto possui algum outro tipo que não o de objeto simples.
|
|
1142
|
-
// Normalmente executam quando uma biblioteca é importada, e estamos tentando
|
|
1143
|
-
// obter alguma propriedade ou método desse objeto.
|
|
1144
|
-
// Caso 1: Função tradicional do JavaScript.
|
|
1145
|
-
if (typeof objeto[expressao.simbolo.lexema] === primitivos_1.default.FUNCAO) {
|
|
1146
|
-
return objeto[expressao.simbolo.lexema];
|
|
1147
|
-
}
|
|
1148
|
-
// Caso 2: Objeto tradicional do JavaScript.
|
|
1149
|
-
if (typeof objeto[expressao.simbolo.lexema] === primitivos_1.default.OBJETO) {
|
|
1150
|
-
return objeto[expressao.simbolo.lexema];
|
|
1151
|
-
}
|
|
1152
|
-
// A partir daqui, presume-se que o objeto é uma das estruturas
|
|
1153
|
-
// de Delégua.
|
|
1154
|
-
if (objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1155
|
-
return objeto.componentes[expressao.simbolo.lexema] || null;
|
|
1156
|
-
}
|
|
1157
|
-
let tipoObjeto = variavelObjeto.tipo;
|
|
1158
|
-
if (tipoObjeto === null || tipoObjeto === undefined) {
|
|
1159
|
-
tipoObjeto = (0, inferenciador_1.inferirTipoVariavel)(variavelObjeto);
|
|
1160
|
-
}
|
|
1161
|
-
// Como internamente um dicionário de Delégua é simplesmente um objeto de
|
|
1162
|
-
// JavaScript, as primitivas de dicionário, especificamente, são tratadas
|
|
1163
|
-
// mais acima.
|
|
1164
|
-
switch (tipoObjeto) {
|
|
1165
|
-
case delegua_2.default.INTEIRO:
|
|
1166
|
-
case delegua_2.default.NUMERO:
|
|
1167
|
-
case delegua_2.default.NÚMERO:
|
|
1168
|
-
const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.simbolo.lexema];
|
|
1169
|
-
if (metodoDePrimitivaNumero) {
|
|
1170
|
-
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaNumero);
|
|
1171
|
-
}
|
|
1172
|
-
break;
|
|
1173
|
-
case delegua_2.default.TEXTO:
|
|
1174
|
-
const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.simbolo.lexema];
|
|
1175
|
-
if (metodoDePrimitivaTexto) {
|
|
1176
|
-
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaTexto);
|
|
1177
|
-
}
|
|
1178
|
-
break;
|
|
1179
|
-
case delegua_2.default.VETOR:
|
|
1180
|
-
const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.simbolo.lexema];
|
|
1181
|
-
if (metodoDePrimitivaVetor) {
|
|
1182
|
-
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaVetor);
|
|
1183
|
-
}
|
|
1184
|
-
break;
|
|
1185
|
-
}
|
|
1186
|
-
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método para objeto ou primitiva não encontrado: ${expressao.simbolo.lexema}.`, expressao.linha));
|
|
1187
|
-
}
|
|
1188
|
-
visitarExpressaoIsto(expressao) {
|
|
1189
|
-
return this.procurarVariavel(expressao.palavraChave);
|
|
1190
|
-
}
|
|
1191
|
-
visitarDeclaracaoAleatorio(declaracao) {
|
|
1192
|
-
return Promise.resolve();
|
|
1193
|
-
}
|
|
1194
|
-
async visitarExpressaoDicionario(expressao) {
|
|
1195
|
-
const dicionario = {};
|
|
1196
|
-
for (let i = 0; i < expressao.chaves.length; i++) {
|
|
1197
|
-
const promises = await Promise.all([this.avaliar(expressao.chaves[i]), this.avaliar(expressao.valores[i])]);
|
|
1198
|
-
dicionario[promises[0]] = promises[1];
|
|
1199
|
-
}
|
|
1200
|
-
return dicionario;
|
|
1201
|
-
}
|
|
1202
|
-
async visitarExpressaoVetor(expressao) {
|
|
1203
|
-
const valores = [];
|
|
1204
|
-
for (let i = 0; i < expressao.valores.length; i++) {
|
|
1205
|
-
valores.push(await this.avaliar(expressao.valores[i]));
|
|
1206
|
-
}
|
|
1207
|
-
return valores;
|
|
1208
|
-
}
|
|
1209
|
-
visitarExpressaoSuper(expressao) {
|
|
1210
|
-
const superClasse = this.pilhaEscoposExecucao.obterVariavelPorNome('super');
|
|
1211
|
-
const objeto = this.pilhaEscoposExecucao.obterVariavelPorNome('isto');
|
|
1212
|
-
const metodo = superClasse.valor.encontrarMetodo(expressao.metodo.lexema);
|
|
1213
|
-
if (metodo === undefined) {
|
|
1214
|
-
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.metodo, 'Método chamado indefinido.', expressao.linha);
|
|
1215
|
-
}
|
|
1216
|
-
metodo.instancia = objeto.valor;
|
|
1217
|
-
return metodo;
|
|
1218
|
-
}
|
|
1219
|
-
/**
|
|
1220
|
-
* Executa expressão de definição de variável.
|
|
1221
|
-
* @param declaracao A declaração Var
|
|
1222
|
-
* @returns Sempre retorna nulo.
|
|
1223
|
-
*/
|
|
1224
|
-
async visitarDeclaracaoVar(declaracao) {
|
|
1225
|
-
const valorFinal = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
1226
|
-
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
|
|
1227
|
-
return null;
|
|
1228
|
-
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Executa expressão de definição de múltiplas variáveis.
|
|
1231
|
-
* @param declaracao A declaração `VarMultiplo`.
|
|
1232
|
-
* @returns Sempre retorna nulo.
|
|
1233
|
-
*/
|
|
1234
|
-
async visitarDeclaracaoVarMultiplo(declaracao) {
|
|
1235
|
-
const valoresFinais = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
1236
|
-
for (let [indice, valor] of valoresFinais.entries()) {
|
|
1237
|
-
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolos[indice].lexema, valor, declaracao.tipo);
|
|
1238
|
-
}
|
|
1239
|
-
return null;
|
|
1240
|
-
}
|
|
1241
|
-
paraTexto(objeto) {
|
|
1242
|
-
if (objeto === null || objeto === undefined)
|
|
1243
|
-
return delegua_2.default.NULO;
|
|
1244
|
-
if (typeof objeto === primitivos_1.default.BOOLEANO) {
|
|
1245
|
-
return objeto ? 'verdadeiro' : 'falso';
|
|
1246
|
-
}
|
|
1247
|
-
if (objeto instanceof quebras_1.RetornoQuebra) {
|
|
1248
|
-
if (typeof objeto.valor === 'boolean')
|
|
1249
|
-
return objeto.valor ? 'verdadeiro' : 'falso';
|
|
1250
|
-
}
|
|
1251
|
-
if (objeto instanceof Date) {
|
|
1252
|
-
const formato = Intl.DateTimeFormat('pt', {
|
|
1253
|
-
dateStyle: 'full',
|
|
1254
|
-
timeStyle: 'full',
|
|
1255
|
-
});
|
|
1256
|
-
return formato.format(objeto);
|
|
1257
|
-
}
|
|
1258
|
-
if (Array.isArray(objeto)) {
|
|
1259
|
-
let retornoVetor = '[';
|
|
1260
|
-
for (let elemento of objeto) {
|
|
1261
|
-
retornoVetor += typeof elemento === 'string' ? `'${elemento}', ` : `${this.paraTexto(elemento)}, `;
|
|
1262
|
-
}
|
|
1263
|
-
if (retornoVetor.length > 1) {
|
|
1264
|
-
retornoVetor = retornoVetor.slice(0, -2);
|
|
1265
|
-
}
|
|
1266
|
-
retornoVetor += ']';
|
|
1267
|
-
return retornoVetor;
|
|
1268
|
-
}
|
|
1269
|
-
if (objeto.valor instanceof estruturas_1.ObjetoPadrao)
|
|
1270
|
-
return objeto.valor.paraTexto();
|
|
1271
|
-
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto instanceof estruturas_1.DeleguaFuncao)
|
|
1272
|
-
return objeto.paraTexto();
|
|
1273
|
-
switch (objeto.constructor.name) {
|
|
1274
|
-
case 'Object':
|
|
1275
|
-
if ('tipo' in objeto) {
|
|
1276
|
-
switch (objeto.tipo) {
|
|
1277
|
-
case 'dicionário':
|
|
1278
|
-
return JSON.stringify(objeto.valor);
|
|
1279
|
-
default:
|
|
1280
|
-
return objeto.valor;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
if (typeof objeto === primitivos_1.default.OBJETO) {
|
|
1285
|
-
for (const obj in objeto) {
|
|
1286
|
-
let valor = objeto[obj];
|
|
1287
|
-
if (typeof valor === primitivos_1.default.BOOLEANO) {
|
|
1288
|
-
valor = valor ? 'verdadeiro' : 'falso';
|
|
1289
|
-
objeto[obj] = valor;
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
return JSON.stringify(objeto);
|
|
1293
|
-
}
|
|
1294
|
-
return objeto.toString();
|
|
1295
|
-
}
|
|
1296
|
-
/**
|
|
1297
|
-
* Efetivamente executa uma declaração.
|
|
1298
|
-
* @param declaracao A declaração a ser executada.
|
|
1299
|
-
* @param mostrarResultado Se resultado deve ser mostrado ou não. Normalmente usado
|
|
1300
|
-
* pelo modo LAIR.
|
|
1301
|
-
*/
|
|
1302
|
-
async executar(declaracao, mostrarResultado = false) {
|
|
1303
|
-
const resultado = await declaracao.aceitar(this);
|
|
1304
|
-
/* console.log("Resultado aceitar: " + resultado, this); */
|
|
1305
|
-
if (mostrarResultado) {
|
|
1306
|
-
this.funcaoDeRetorno(this.paraTexto(resultado));
|
|
1307
|
-
}
|
|
1308
|
-
if (resultado || typeof resultado === primitivos_1.default.BOOLEANO) {
|
|
1309
|
-
this.resultadoInterpretador.push(this.paraTexto(resultado));
|
|
1310
|
-
}
|
|
1311
|
-
return resultado;
|
|
1312
|
-
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Executa o último escopo empilhado no topo na pilha de escopos do interpretador.
|
|
1315
|
-
* Esse método pega exceções, mas apenas as devolve.
|
|
1316
|
-
*
|
|
1317
|
-
* O tratamento das exceções é feito de acordo com o bloco chamador.
|
|
1318
|
-
* Por exemplo, em `tente ... pegue ... finalmente`, a exceção é capturada e tratada.
|
|
1319
|
-
* Em outros blocos, pode ser desejável ter o erro em tela.
|
|
1320
|
-
* @param manterAmbiente Se verdadeiro, ambiente do topo da pilha de escopo é copiado para o ambiente imediatamente abaixo.
|
|
1321
|
-
* @returns O resultado da execução do escopo, se houver.
|
|
1322
|
-
*/
|
|
1323
|
-
async executarUltimoEscopo(manterAmbiente = false) {
|
|
1324
|
-
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
1325
|
-
try {
|
|
1326
|
-
let retornoExecucao;
|
|
1327
|
-
for (; !(retornoExecucao instanceof quebras_1.Quebra) && ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length; ultimoEscopo.declaracaoAtual++) {
|
|
1328
|
-
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
|
|
1329
|
-
}
|
|
1330
|
-
return retornoExecucao;
|
|
1331
|
-
}
|
|
1332
|
-
catch (erro) {
|
|
1333
|
-
const declaracaoAtual = ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual];
|
|
1334
|
-
if (!this.emDeclaracaoTente) {
|
|
1335
|
-
this.erros.push({
|
|
1336
|
-
erroInterno: erro,
|
|
1337
|
-
linha: declaracaoAtual.linha,
|
|
1338
|
-
hashArquivo: declaracaoAtual.hashArquivo,
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
return Promise.reject(erro);
|
|
1342
|
-
}
|
|
1343
|
-
finally {
|
|
1344
|
-
this.pilhaEscoposExecucao.removerUltimo();
|
|
1345
|
-
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
1346
|
-
if (manterAmbiente) {
|
|
1347
|
-
escopoAnterior.ambiente.valores = Object.assign(escopoAnterior.ambiente.valores, ultimoEscopo.ambiente.valores);
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Interpretação sem depurador, com medição de performance.
|
|
1353
|
-
* Método que efetivamente inicia o processo de interpretação.
|
|
1354
|
-
* @param declaracoes Um vetor de declarações gerado pelo Avaliador Sintático.
|
|
1355
|
-
* @param manterAmbiente Se ambiente de execução (variáveis, classes, etc.) deve ser mantido. Normalmente usado
|
|
1356
|
-
* pelo modo REPL (LAIR).
|
|
1357
|
-
* @returns Um objeto com o resultado da interpretação.
|
|
1358
|
-
*/
|
|
1359
|
-
async interpretar(declaracoes, manterAmbiente = false) {
|
|
1360
|
-
this.erros = [];
|
|
1361
|
-
this.emDeclaracaoTente = false;
|
|
1362
|
-
const escopoExecucao = {
|
|
1363
|
-
declaracoes: declaracoes,
|
|
1364
|
-
declaracaoAtual: 0,
|
|
1365
|
-
ambiente: new espaco_variaveis_1.EspacoVariaveis(),
|
|
1366
|
-
finalizado: false,
|
|
1367
|
-
tipo: 'outro',
|
|
1368
|
-
emLacoRepeticao: false,
|
|
1369
|
-
};
|
|
1370
|
-
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
1371
|
-
const inicioInterpretacao = (0, browser_process_hrtime_1.default)();
|
|
1372
|
-
try {
|
|
1373
|
-
const retornoOuErro = await this.executarUltimoEscopo(manterAmbiente);
|
|
1374
|
-
if (retornoOuErro instanceof excecoes_1.ErroEmTempoDeExecucao) {
|
|
1375
|
-
this.erros.push(retornoOuErro);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
catch (erro) {
|
|
1379
|
-
this.erros.push({
|
|
1380
|
-
erroInterno: erro,
|
|
1381
|
-
linha: -1,
|
|
1382
|
-
hashArquivo: -1,
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
finally {
|
|
1386
|
-
if (this.performance) {
|
|
1387
|
-
const deltaInterpretacao = (0, browser_process_hrtime_1.default)(inicioInterpretacao);
|
|
1388
|
-
console.log(`[Interpretador] Tempo para interpretaçao: ${deltaInterpretacao[0] * 1e9 + deltaInterpretacao[1]}ns`);
|
|
1389
|
-
}
|
|
1390
|
-
const retorno = {
|
|
1391
|
-
erros: this.erros,
|
|
1392
|
-
resultado: this.resultadoInterpretador,
|
|
1393
|
-
};
|
|
1394
|
-
this.resultadoInterpretador = [];
|
|
1395
|
-
return retorno;
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
exports.InterpretadorBase = InterpretadorBase;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.InterpretadorBase = void 0;
|
|
7
|
+
const browser_process_hrtime_1 = __importDefault(require("browser-process-hrtime"));
|
|
8
|
+
const estruturas_1 = require("../estruturas");
|
|
9
|
+
const construtos_1 = require("../construtos");
|
|
10
|
+
const pilha_escopos_execucao_1 = require("./pilha-escopos-execucao");
|
|
11
|
+
const quebras_1 = require("../quebras");
|
|
12
|
+
const inferenciador_1 = require("./inferenciador");
|
|
13
|
+
const metodo_primitiva_1 = require("../estruturas/metodo-primitiva");
|
|
14
|
+
const lexador_1 = require("../lexador");
|
|
15
|
+
const avaliador_sintatico_1 = require("../avaliador-sintatico");
|
|
16
|
+
const espaco_variaveis_1 = require("../espaco-variaveis");
|
|
17
|
+
const comum_1 = require("./comum");
|
|
18
|
+
const excecoes_1 = require("../excecoes");
|
|
19
|
+
const primitivas_dicionario_1 = __importDefault(require("../bibliotecas/primitivas-dicionario"));
|
|
20
|
+
const primitivas_numero_1 = __importDefault(require("../bibliotecas/primitivas-numero"));
|
|
21
|
+
const primitivas_texto_1 = __importDefault(require("../bibliotecas/primitivas-texto"));
|
|
22
|
+
const primitivas_vetor_1 = __importDefault(require("../bibliotecas/primitivas-vetor"));
|
|
23
|
+
const delegua_1 = __importDefault(require("../tipos-de-simbolos/delegua"));
|
|
24
|
+
const primitivos_1 = __importDefault(require("../tipos-de-dados/primitivos"));
|
|
25
|
+
const delegua_2 = __importDefault(require("../tipos-de-dados/delegua"));
|
|
26
|
+
/**
|
|
27
|
+
* O Interpretador visita todos os elementos complexos gerados pelo avaliador sintático (_parser_),
|
|
28
|
+
* e de fato executa a lógica de programação descrita no código.
|
|
29
|
+
*
|
|
30
|
+
* O Interpretador Base não contém dependências com o Node.js. É
|
|
31
|
+
* recomendado para uso em execuções que ocorrem no navegador de internet.
|
|
32
|
+
*/
|
|
33
|
+
class InterpretadorBase {
|
|
34
|
+
constructor(diretorioBase, performance = false, funcaoDeRetorno = null, funcaoDeRetornoMesmaLinha = null) {
|
|
35
|
+
this.resultadoInterpretador = [];
|
|
36
|
+
this.funcaoDeRetorno = null;
|
|
37
|
+
this.funcaoDeRetornoMesmaLinha = null;
|
|
38
|
+
this.interfaceDeEntrada = null; // Originalmente é `readline.Interface`
|
|
39
|
+
this.interfaceEntradaSaida = null;
|
|
40
|
+
this.emDeclaracaoTente = false;
|
|
41
|
+
this.microLexador = new lexador_1.MicroLexador();
|
|
42
|
+
this.microAvaliadorSintatico = new avaliador_sintatico_1.MicroAvaliadorSintatico();
|
|
43
|
+
this.regexInterpolacao = /\${(.*?)}/g;
|
|
44
|
+
this.tiposNumericos = [
|
|
45
|
+
delegua_2.default.INTEIRO,
|
|
46
|
+
delegua_2.default.NUMERO,
|
|
47
|
+
delegua_2.default.NÚMERO,
|
|
48
|
+
delegua_2.default.REAL
|
|
49
|
+
];
|
|
50
|
+
this.diretorioBase = diretorioBase;
|
|
51
|
+
this.performance = performance;
|
|
52
|
+
this.funcaoDeRetorno = funcaoDeRetorno || console.log;
|
|
53
|
+
this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout);
|
|
54
|
+
this.erros = [];
|
|
55
|
+
this.declaracoes = [];
|
|
56
|
+
this.resultadoInterpretador = [];
|
|
57
|
+
// Isso existe por causa de Potigol.
|
|
58
|
+
// Para acessar uma variável de classe, não é preciso a palavra `isto`.
|
|
59
|
+
this.expandirPropriedadesDeObjetosEmEspacoVariaveis = false;
|
|
60
|
+
// Por padrão é verdadeiro porque Delégua e Pituguês usam
|
|
61
|
+
// o interpretador base como implementação padrão.
|
|
62
|
+
this.requerDeclaracaoPropriedades = true;
|
|
63
|
+
this.pilhaEscoposExecucao = new pilha_escopos_execucao_1.PilhaEscoposExecucao();
|
|
64
|
+
const escopoExecucao = {
|
|
65
|
+
declaracoes: [],
|
|
66
|
+
declaracaoAtual: 0,
|
|
67
|
+
ambiente: new espaco_variaveis_1.EspacoVariaveis(),
|
|
68
|
+
finalizado: false,
|
|
69
|
+
tipo: 'outro',
|
|
70
|
+
emLacoRepeticao: false,
|
|
71
|
+
};
|
|
72
|
+
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
73
|
+
(0, comum_1.carregarBibliotecasGlobais)(this.pilhaEscoposExecucao);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Construtos de comentários não têm utilidade para o Interpretador.
|
|
77
|
+
* Apenas retornamos `Promise.resolve()` para não termos erros.
|
|
78
|
+
* @param declaracao A declaração de comentário.
|
|
79
|
+
*/
|
|
80
|
+
visitarDeclaracaoComentario(declaracao) {
|
|
81
|
+
return Promise.resolve();
|
|
82
|
+
}
|
|
83
|
+
async visitarDeclaracaoTendoComo(declaracao) {
|
|
84
|
+
const retornoInicializacao = await this.avaliar(declaracao.inicializacaoVariavel);
|
|
85
|
+
this.pilhaEscoposExecucao.definirConstante(declaracao.simboloVariavel.lexema, retornoInicializacao);
|
|
86
|
+
await this.executar(declaracao.corpo);
|
|
87
|
+
if (retornoInicializacao instanceof estruturas_1.ObjetoDeleguaClasse) {
|
|
88
|
+
const metodoFinalizar = retornoInicializacao.classe.metodos['finalizar'];
|
|
89
|
+
if (metodoFinalizar) {
|
|
90
|
+
const chamavel = metodoFinalizar.funcaoPorMetodoDeClasse(retornoInicializacao);
|
|
91
|
+
chamavel.chamar(this, []);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
async visitarDeclaracaoInicioAlgoritmo(declaracao) {
|
|
97
|
+
throw new Error('Método não implementado.');
|
|
98
|
+
}
|
|
99
|
+
async visitarDeclaracaoCabecalhoPrograma(declaracao) {
|
|
100
|
+
throw new Error('Método não implementado.');
|
|
101
|
+
}
|
|
102
|
+
async visitarExpressaoTupla(expressao) {
|
|
103
|
+
const chaves = Object.keys(expressao);
|
|
104
|
+
const valores = [];
|
|
105
|
+
for (let chave of chaves) {
|
|
106
|
+
const valor = await this.avaliar(expressao[chave]);
|
|
107
|
+
valores.push(valor);
|
|
108
|
+
}
|
|
109
|
+
return valores;
|
|
110
|
+
}
|
|
111
|
+
async visitarExpressaoAtribuicaoPorIndicesMatriz(expressao) {
|
|
112
|
+
throw new Error('Método não implementado.');
|
|
113
|
+
}
|
|
114
|
+
async visitarExpressaoAcessoElementoMatriz(expressao) {
|
|
115
|
+
throw new Error('Método não implementado.');
|
|
116
|
+
}
|
|
117
|
+
textoParaRegex(texto) {
|
|
118
|
+
const match = texto.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/);
|
|
119
|
+
return match
|
|
120
|
+
? new RegExp(match[2], match[3]
|
|
121
|
+
.split('')
|
|
122
|
+
.filter((char, pos, flagArr) => flagArr.indexOf(char) === pos)
|
|
123
|
+
.join(''))
|
|
124
|
+
: new RegExp(texto);
|
|
125
|
+
}
|
|
126
|
+
visitarExpressaoExpressaoRegular(expressao) {
|
|
127
|
+
return Promise.resolve(this.textoParaRegex(expressao.valor));
|
|
128
|
+
}
|
|
129
|
+
async visitarExpressaoTipoDe(expressao) {
|
|
130
|
+
let tipoDe = expressao.valor;
|
|
131
|
+
if (tipoDe instanceof construtos_1.Agrupamento ||
|
|
132
|
+
tipoDe instanceof construtos_1.Binario ||
|
|
133
|
+
tipoDe instanceof construtos_1.Chamada ||
|
|
134
|
+
tipoDe instanceof construtos_1.Dicionario ||
|
|
135
|
+
tipoDe instanceof construtos_1.TipoDe ||
|
|
136
|
+
tipoDe instanceof construtos_1.Unario ||
|
|
137
|
+
tipoDe instanceof construtos_1.Variavel) {
|
|
138
|
+
tipoDe = await this.avaliar(tipoDe);
|
|
139
|
+
return tipoDe.tipo || (0, inferenciador_1.inferirTipoVariavel)(tipoDe);
|
|
140
|
+
}
|
|
141
|
+
return (0, inferenciador_1.inferirTipoVariavel)((tipoDe === null || tipoDe === void 0 ? void 0 : tipoDe.valores) || tipoDe);
|
|
142
|
+
}
|
|
143
|
+
// TODO: Depreciado. Priorizar `visitarExpressaoTipoDe`.
|
|
144
|
+
async visitarExpressaoQualTipo(expressao) {
|
|
145
|
+
throw new Error('Método não implementado.');
|
|
146
|
+
}
|
|
147
|
+
async visitarExpressaoFalhar(expressao) {
|
|
148
|
+
var _a;
|
|
149
|
+
const textoFalha = (_a = expressao.explicacao.valor) !== null && _a !== void 0 ? _a : (await this.avaliar(expressao.explicacao)).valor;
|
|
150
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, textoFalha, expressao.linha);
|
|
151
|
+
}
|
|
152
|
+
async visitarExpressaoFimPara(declaracao) {
|
|
153
|
+
throw new Error('Método não implementado.');
|
|
154
|
+
}
|
|
155
|
+
async avaliar(expressao) {
|
|
156
|
+
// Descomente o código abaixo quando precisar detectar expressões undefined ou nulas.
|
|
157
|
+
// Por algum motivo o depurador do VSCode não funciona direito aqui
|
|
158
|
+
// com breakpoint condicional.
|
|
159
|
+
/* if (expressao === null || expressao === undefined) {
|
|
160
|
+
console.log('Aqui');
|
|
161
|
+
} */
|
|
162
|
+
return await expressao.aceitar(this);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execução da leitura de valores da entrada configurada no
|
|
166
|
+
* início da aplicação.
|
|
167
|
+
* @param expressao Expressão do tipo Leia
|
|
168
|
+
* @returns Promise com o resultado da leitura.
|
|
169
|
+
*/
|
|
170
|
+
async visitarExpressaoLeia(expressao) {
|
|
171
|
+
const mensagem = expressao.argumentos && expressao.argumentos[0] ? expressao.argumentos[0].valor : '> ';
|
|
172
|
+
return new Promise((resolucao) => this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
173
|
+
resolucao(resposta);
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Execução da leitura de valores da entrada configurada no
|
|
178
|
+
* início da aplicação.
|
|
179
|
+
* @param expressao Expressão do tipo `LeiaMultiplo`.
|
|
180
|
+
* @returns Promise com o resultado da leitura.
|
|
181
|
+
*/
|
|
182
|
+
async visitarExpressaoLeiaMultiplo(expressao) {
|
|
183
|
+
const mensagem = '> ';
|
|
184
|
+
if (expressao.argumento instanceof construtos_1.Literal) {
|
|
185
|
+
let valor = expressao.argumento.valor;
|
|
186
|
+
if (typeof valor === primitivos_1.default.TEXTO) {
|
|
187
|
+
return new Promise((resolucao) => this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
188
|
+
resolucao(String(resposta)
|
|
189
|
+
.split(valor)
|
|
190
|
+
.filter((r) => !/(\s+)/.test(r)));
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
let respostas = [];
|
|
194
|
+
for (let i = 0; i < valor; i++) {
|
|
195
|
+
this.interfaceEntradaSaida.question(mensagem, (resposta) => {
|
|
196
|
+
respostas.push(resposta);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return Promise.resolve(respostas);
|
|
200
|
+
}
|
|
201
|
+
return Promise.resolve();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Retira a interpolação de um texto.
|
|
205
|
+
* @param {texto} texto O texto
|
|
206
|
+
* @param {any[]} variaveis A lista de variaveis interpoladas
|
|
207
|
+
* @returns O texto com o valor das variaveis.
|
|
208
|
+
*/
|
|
209
|
+
retirarInterpolacao(texto, variaveis) {
|
|
210
|
+
let textoFinal = texto;
|
|
211
|
+
variaveis.forEach((elemento) => {
|
|
212
|
+
var _a, _b, _c;
|
|
213
|
+
if (((_a = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _a === void 0 ? void 0 : _a.tipo) === delegua_2.default.LOGICO) {
|
|
214
|
+
textoFinal = textoFinal.replace('${' + elemento.variavel + '}', this.paraTexto((_b = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _b === void 0 ? void 0 : _b.valor));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const valor = ((_c = elemento === null || elemento === void 0 ? void 0 : elemento.valor) === null || _c === void 0 ? void 0 : _c.hasOwnProperty('valor')) ? elemento === null || elemento === void 0 ? void 0 : elemento.valor.valor : elemento === null || elemento === void 0 ? void 0 : elemento.valor;
|
|
218
|
+
textoFinal = textoFinal.replace('${' + elemento.variavel + '}', `${this.paraTexto(valor)}`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return textoFinal;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Resolve todas as interpolações em um texto.
|
|
225
|
+
* @param {texto} textoOriginal O texto original com as variáveis interpoladas.
|
|
226
|
+
* @returns Uma lista de variáveis interpoladas.
|
|
227
|
+
*/
|
|
228
|
+
async resolverInterpolacoes(textoOriginal, linha) {
|
|
229
|
+
const variaveis = textoOriginal.match(this.regexInterpolacao);
|
|
230
|
+
let resultadosAvaliacaoSintatica = variaveis.map((s) => {
|
|
231
|
+
const nomeVariavel = s.replace(/[\$\{\}]*/gm, '');
|
|
232
|
+
let microLexador = this.microLexador.mapear(nomeVariavel);
|
|
233
|
+
const resultadoMicroAvaliadorSintatico = this.microAvaliadorSintatico.analisar(microLexador, linha);
|
|
234
|
+
return {
|
|
235
|
+
nomeVariavel,
|
|
236
|
+
resultadoMicroAvaliadorSintatico,
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
// TODO: Verificar erros do `resultadosAvaliacaoSintatica`.
|
|
240
|
+
const resolucoesPromises = await Promise.all(resultadosAvaliacaoSintatica
|
|
241
|
+
.flatMap((r) => r.resultadoMicroAvaliadorSintatico.declaracoes)
|
|
242
|
+
.map((d) => this.avaliar(d)));
|
|
243
|
+
return resolucoesPromises.map((item, indice) => ({
|
|
244
|
+
variavel: resultadosAvaliacaoSintatica[indice].nomeVariavel,
|
|
245
|
+
valor: item,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
async visitarExpressaoLiteral(expressao) {
|
|
249
|
+
if (this.regexInterpolacao.test(expressao.valor)) {
|
|
250
|
+
const variaveis = await this.resolverInterpolacoes(expressao.valor, expressao.linha);
|
|
251
|
+
return this.retirarInterpolacao(expressao.valor, variaveis);
|
|
252
|
+
}
|
|
253
|
+
return expressao.valor;
|
|
254
|
+
}
|
|
255
|
+
async visitarExpressaoAgrupamento(expressao) {
|
|
256
|
+
return await this.avaliar(expressao.expressao);
|
|
257
|
+
}
|
|
258
|
+
eVerdadeiro(objeto) {
|
|
259
|
+
if (objeto === null)
|
|
260
|
+
return false;
|
|
261
|
+
if (typeof objeto === primitivos_1.default.BOOLEANO)
|
|
262
|
+
return Boolean(objeto);
|
|
263
|
+
if (objeto.hasOwnProperty('valor')) {
|
|
264
|
+
return Boolean(objeto.valor);
|
|
265
|
+
}
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
verificarOperandoNumero(operador, operando) {
|
|
269
|
+
if (typeof operando === primitivos_1.default.NUMERO || operando.tipo === delegua_2.default.NUMERO)
|
|
270
|
+
return;
|
|
271
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(operador, 'Operando precisa ser um número.', Number(operador.linha));
|
|
272
|
+
}
|
|
273
|
+
async visitarExpressaoUnaria(expressao) {
|
|
274
|
+
const operando = await this.avaliar(expressao.operando);
|
|
275
|
+
let valor = operando.hasOwnProperty('valor') ? operando.valor : operando;
|
|
276
|
+
switch (expressao.operador.tipo) {
|
|
277
|
+
case delegua_1.default.SUBTRACAO:
|
|
278
|
+
this.verificarOperandoNumero(expressao.operador, valor);
|
|
279
|
+
return -valor;
|
|
280
|
+
case delegua_1.default.NEGACAO:
|
|
281
|
+
return !this.eVerdadeiro(valor);
|
|
282
|
+
case delegua_1.default.BIT_NOT:
|
|
283
|
+
return ~valor;
|
|
284
|
+
// Para incrementar e decrementar, primeiro precisamos saber se o operador
|
|
285
|
+
// veio antes do literal ou variável.
|
|
286
|
+
// Se veio antes e o operando é uma variável, precisamos incrementar/decrementar,
|
|
287
|
+
// armazenar o valor da variável pra só então devolver o valor.
|
|
288
|
+
case delegua_1.default.INCREMENTAR:
|
|
289
|
+
if (expressao.incidenciaOperador === 'ANTES') {
|
|
290
|
+
valor++;
|
|
291
|
+
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
292
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, valor);
|
|
293
|
+
}
|
|
294
|
+
return valor;
|
|
295
|
+
}
|
|
296
|
+
const valorAnteriorIncremento = valor;
|
|
297
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, ++valor);
|
|
298
|
+
return valorAnteriorIncremento;
|
|
299
|
+
case delegua_1.default.DECREMENTAR:
|
|
300
|
+
if (expressao.incidenciaOperador === 'ANTES') {
|
|
301
|
+
valor--;
|
|
302
|
+
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
303
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, valor);
|
|
304
|
+
}
|
|
305
|
+
return valor;
|
|
306
|
+
}
|
|
307
|
+
const valorAnteriorDecremento = valor;
|
|
308
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.operando.simbolo, --valor);
|
|
309
|
+
return valorAnteriorDecremento;
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Formata uma saída de acordo com o número e espaços e casas decimais solicitados.
|
|
315
|
+
* @param declaracao A declaração de formatação de escrita.
|
|
316
|
+
* @returns {string} A saída formatada como texto e os respectivos parâmetros aplicados.
|
|
317
|
+
*/
|
|
318
|
+
async visitarExpressaoFormatacaoEscrita(declaracao) {
|
|
319
|
+
let resultado = '';
|
|
320
|
+
const conteudo = await this.avaliar(declaracao.expressao);
|
|
321
|
+
const valorConteudo = (conteudo === null || conteudo === void 0 ? void 0 : conteudo.hasOwnProperty('valor')) ? conteudo.valor : conteudo;
|
|
322
|
+
const tipoConteudo = conteudo.hasOwnProperty('tipo') ? conteudo.tipo : typeof conteudo;
|
|
323
|
+
resultado = valorConteudo;
|
|
324
|
+
if ([delegua_2.default.NUMERO, primitivos_1.default.NUMERO].includes(tipoConteudo) &&
|
|
325
|
+
declaracao.casasDecimais > 0) {
|
|
326
|
+
resultado = valorConteudo.toLocaleString('pt', { maximumFractionDigits: declaracao.casasDecimais });
|
|
327
|
+
}
|
|
328
|
+
if (declaracao.espacos > 0) {
|
|
329
|
+
resultado += ' '.repeat(declaracao.espacos);
|
|
330
|
+
}
|
|
331
|
+
return resultado;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Lógica para verificação de valores iguais, para Delégua e alguns dialetos.
|
|
335
|
+
* @param esquerda Uma variável.
|
|
336
|
+
* @param direita Outra variável.
|
|
337
|
+
* @returns Verdadeiro se são iguais. Falso em caso contrário.
|
|
338
|
+
*/
|
|
339
|
+
eIgual(esquerda, direita) {
|
|
340
|
+
if (esquerda === null && direita === null)
|
|
341
|
+
return true;
|
|
342
|
+
if (esquerda === null)
|
|
343
|
+
return false;
|
|
344
|
+
return esquerda === direita;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Verifica se operandos são números, que podem ser tanto variáveis puras do JavaScript
|
|
348
|
+
* (neste caso, `number`), ou podem ser variáveis de Delégua com inferência (`VariavelInterface`).
|
|
349
|
+
* @param operador O símbolo do operador.
|
|
350
|
+
* @param direita O operando direito.
|
|
351
|
+
* @param esquerda O operando esquerdo.
|
|
352
|
+
* @returns Se ambos os operandos são números ou não.
|
|
353
|
+
*/
|
|
354
|
+
verificarOperandosNumeros(operador, direita, esquerda) {
|
|
355
|
+
const tipoDireita = direita.tipo
|
|
356
|
+
? direita.tipo
|
|
357
|
+
: typeof direita === primitivos_1.default.NUMERO
|
|
358
|
+
? delegua_2.default.NUMERO
|
|
359
|
+
: String(NaN);
|
|
360
|
+
const tipoEsquerda = esquerda.tipo
|
|
361
|
+
? esquerda.tipo
|
|
362
|
+
: typeof esquerda === primitivos_1.default.NUMERO
|
|
363
|
+
? delegua_2.default.NUMERO
|
|
364
|
+
: String(NaN);
|
|
365
|
+
if (this.tiposNumericos.includes(tipoDireita) && this.tiposNumericos.includes(tipoEsquerda))
|
|
366
|
+
return;
|
|
367
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(operador, 'Operadores precisam ser números.', operador.linha);
|
|
368
|
+
}
|
|
369
|
+
async visitarExpressaoBinaria(expressao) {
|
|
370
|
+
const esquerda = await this.avaliar(expressao.esquerda);
|
|
371
|
+
const direita = await this.avaliar(expressao.direita);
|
|
372
|
+
const valorEsquerdo = (esquerda === null || esquerda === void 0 ? void 0 : esquerda.hasOwnProperty('valor')) ? esquerda.valor : esquerda;
|
|
373
|
+
const valorDireito = (direita === null || direita === void 0 ? void 0 : direita.hasOwnProperty('valor')) ? direita.valor : direita;
|
|
374
|
+
const tipoEsquerdo = (esquerda === null || esquerda === void 0 ? void 0 : esquerda.hasOwnProperty('tipo')) ? esquerda.tipo : (0, inferenciador_1.inferirTipoVariavel)(esquerda);
|
|
375
|
+
const tipoDireito = (direita === null || direita === void 0 ? void 0 : direita.hasOwnProperty('tipo')) ? direita.tipo : (0, inferenciador_1.inferirTipoVariavel)(direita);
|
|
376
|
+
switch (expressao.operador.tipo) {
|
|
377
|
+
case delegua_1.default.EXPONENCIACAO:
|
|
378
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
379
|
+
return Math.pow(valorEsquerdo, valorDireito);
|
|
380
|
+
case delegua_1.default.MAIOR:
|
|
381
|
+
if (this.tiposNumericos.includes(tipoEsquerdo) && this.tiposNumericos.includes(tipoDireito)) {
|
|
382
|
+
return Number(valorEsquerdo) > Number(valorDireito);
|
|
383
|
+
}
|
|
384
|
+
return String(valorEsquerdo) > String(valorDireito);
|
|
385
|
+
case delegua_1.default.MAIOR_IGUAL:
|
|
386
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
387
|
+
return Number(valorEsquerdo) >= Number(valorDireito);
|
|
388
|
+
case delegua_1.default.MENOR:
|
|
389
|
+
if (this.tiposNumericos.includes(tipoEsquerdo) && this.tiposNumericos.includes(tipoDireito)) {
|
|
390
|
+
return Number(valorEsquerdo) < Number(valorDireito);
|
|
391
|
+
}
|
|
392
|
+
return String(valorEsquerdo) < String(valorDireito);
|
|
393
|
+
case delegua_1.default.MENOR_IGUAL:
|
|
394
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
395
|
+
return Number(valorEsquerdo) <= Number(valorDireito);
|
|
396
|
+
case delegua_1.default.SUBTRACAO:
|
|
397
|
+
case delegua_1.default.MENOS_IGUAL:
|
|
398
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
399
|
+
return Number(valorEsquerdo) - Number(valorDireito);
|
|
400
|
+
case delegua_1.default.ADICAO:
|
|
401
|
+
case delegua_1.default.MAIS_IGUAL:
|
|
402
|
+
if (this.tiposNumericos.includes(tipoEsquerdo) &&
|
|
403
|
+
this.tiposNumericos.includes(tipoDireito)) {
|
|
404
|
+
return Number(valorEsquerdo) + Number(valorDireito);
|
|
405
|
+
}
|
|
406
|
+
return this.paraTexto(valorEsquerdo) + this.paraTexto(valorDireito);
|
|
407
|
+
case delegua_1.default.DIVISAO:
|
|
408
|
+
case delegua_1.default.DIVISAO_IGUAL:
|
|
409
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
410
|
+
return Number(valorEsquerdo) / Number(valorDireito);
|
|
411
|
+
case delegua_1.default.DIVISAO_INTEIRA:
|
|
412
|
+
case delegua_1.default.DIVISAO_INTEIRA_IGUAL:
|
|
413
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
414
|
+
return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
|
|
415
|
+
case delegua_1.default.MULTIPLICACAO:
|
|
416
|
+
case delegua_1.default.MULTIPLICACAO_IGUAL:
|
|
417
|
+
if (tipoEsquerdo === delegua_2.default.TEXTO || tipoDireito === delegua_2.default.TEXTO) {
|
|
418
|
+
// Sem ambos os valores resolvem como texto, multiplica normal.
|
|
419
|
+
// Se apenas um resolve como texto, o outro repete o
|
|
420
|
+
// texto n vezes, sendo n o valor do outro.
|
|
421
|
+
if (tipoEsquerdo === delegua_2.default.TEXTO && tipoDireito === delegua_2.default.TEXTO) {
|
|
422
|
+
return Number(valorEsquerdo) * Number(valorDireito);
|
|
423
|
+
}
|
|
424
|
+
if (tipoEsquerdo === delegua_2.default.TEXTO) {
|
|
425
|
+
return valorEsquerdo.repeat(Number(valorDireito));
|
|
426
|
+
}
|
|
427
|
+
return valorDireito.repeat(Number(valorEsquerdo));
|
|
428
|
+
}
|
|
429
|
+
return Number(valorEsquerdo) * Number(valorDireito);
|
|
430
|
+
case delegua_1.default.MODULO:
|
|
431
|
+
case delegua_1.default.MODULO_IGUAL:
|
|
432
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
433
|
+
return Number(valorEsquerdo) % Number(valorDireito);
|
|
434
|
+
case delegua_1.default.BIT_AND:
|
|
435
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
436
|
+
return Number(valorEsquerdo) & Number(valorDireito);
|
|
437
|
+
case delegua_1.default.BIT_XOR:
|
|
438
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
439
|
+
return Number(valorEsquerdo) ^ Number(valorDireito);
|
|
440
|
+
case delegua_1.default.BIT_OR:
|
|
441
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
442
|
+
return Number(valorEsquerdo) | Number(valorDireito);
|
|
443
|
+
case delegua_1.default.MENOR_MENOR:
|
|
444
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
445
|
+
return Number(valorEsquerdo) << Number(valorDireito);
|
|
446
|
+
case delegua_1.default.MAIOR_MAIOR:
|
|
447
|
+
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
|
|
448
|
+
return Number(valorEsquerdo) >> Number(valorDireito);
|
|
449
|
+
case delegua_1.default.DIFERENTE:
|
|
450
|
+
return !this.eIgual(valorEsquerdo, valorDireito);
|
|
451
|
+
case delegua_1.default.IGUAL_IGUAL:
|
|
452
|
+
return this.eIgual(valorEsquerdo, valorDireito);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Faz a chamada do método de uma primitiva (por exemplo, número, texto, etc.) com seus
|
|
457
|
+
* respectivos argumentos.
|
|
458
|
+
* @param {Chamada} expressao A expressão de chamada.
|
|
459
|
+
* @param {MetodoPrimitiva} entidadeChamada O método da primitiva chamado.
|
|
460
|
+
* @returns O resultado da chamada do método da primitiva.
|
|
461
|
+
*/
|
|
462
|
+
async chamarMetodoPrimitiva(expressao, entidadeChamada) {
|
|
463
|
+
const argumentosResolvidos = [];
|
|
464
|
+
for (const argumento of expressao.argumentos) {
|
|
465
|
+
const valorResolvido = await this.avaliar(argumento);
|
|
466
|
+
argumentosResolvidos.push((valorResolvido === null || valorResolvido === void 0 ? void 0 : valorResolvido.hasOwnProperty('valor')) ? valorResolvido.valor : valorResolvido);
|
|
467
|
+
}
|
|
468
|
+
return await entidadeChamada.chamar(this, argumentosResolvidos);
|
|
469
|
+
}
|
|
470
|
+
async resolverArgumentosChamada(expressao) {
|
|
471
|
+
const argumentos = [];
|
|
472
|
+
for (let i = 0; i < expressao.argumentos.length; i++) {
|
|
473
|
+
const variavelArgumento = expressao.argumentos[i];
|
|
474
|
+
const nomeArgumento = variavelArgumento.hasOwnProperty('simbolo')
|
|
475
|
+
? variavelArgumento.simbolo.lexema
|
|
476
|
+
: undefined;
|
|
477
|
+
argumentos.push({
|
|
478
|
+
nome: nomeArgumento,
|
|
479
|
+
valor: await this.avaliar(variavelArgumento),
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
return argumentos;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Resolve paraâmetros da chamada de acordo com o tipo da entidade chamada.
|
|
486
|
+
* @param {Chamavel} entidadeChamada A entidade chamada.
|
|
487
|
+
* @returns Os parâmetros resolvidos.
|
|
488
|
+
*/
|
|
489
|
+
resolverParametrosChamada(entidadeChamada) {
|
|
490
|
+
if (entidadeChamada instanceof estruturas_1.DeleguaFuncao) {
|
|
491
|
+
return entidadeChamada.declaracao.parametros;
|
|
492
|
+
}
|
|
493
|
+
if (entidadeChamada instanceof estruturas_1.DescritorTipoClasse) {
|
|
494
|
+
return entidadeChamada.metodos.construtor
|
|
495
|
+
? entidadeChamada.metodos.construtor.declaracao.parametros
|
|
496
|
+
: [];
|
|
497
|
+
}
|
|
498
|
+
return [];
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Executa uma chamada de função, método ou classe.
|
|
502
|
+
* @param expressao A expressão chamada.
|
|
503
|
+
* @returns O resultado da chamada.
|
|
504
|
+
*/
|
|
505
|
+
async visitarExpressaoDeChamada(expressao) {
|
|
506
|
+
try {
|
|
507
|
+
const variavelEntidadeChamada = await this.avaliar(expressao.entidadeChamada);
|
|
508
|
+
if (variavelEntidadeChamada === null) {
|
|
509
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Chamada de função ou método inexistente: ' + String(expressao.entidadeChamada), expressao.linha));
|
|
510
|
+
}
|
|
511
|
+
const entidadeChamada = variavelEntidadeChamada.hasOwnProperty('valor')
|
|
512
|
+
? variavelEntidadeChamada.valor
|
|
513
|
+
: variavelEntidadeChamada;
|
|
514
|
+
if (entidadeChamada instanceof estruturas_1.DeleguaModulo) {
|
|
515
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Entidade chamada é um módulo de Delégua. Provavelmente você quer chamar um de seus componentes?', expressao.linha));
|
|
516
|
+
}
|
|
517
|
+
if (entidadeChamada instanceof metodo_primitiva_1.MetodoPrimitiva) {
|
|
518
|
+
return await this.chamarMetodoPrimitiva(expressao, entidadeChamada);
|
|
519
|
+
}
|
|
520
|
+
const argumentos = await this.resolverArgumentosChamada(expressao);
|
|
521
|
+
// TODO: Aparentemente isso nunca é usado se o bloco de resolução de parâmetros,
|
|
522
|
+
// mais abaixo, também não é.
|
|
523
|
+
// Estudar remoção mais adiante.
|
|
524
|
+
const parametros = this.resolverParametrosChamada(entidadeChamada);
|
|
525
|
+
const aridade = entidadeChamada.aridade ? entidadeChamada.aridade() : entidadeChamada.length;
|
|
526
|
+
// Completar os parâmetros não preenchidos com nulos.
|
|
527
|
+
if (argumentos.length < aridade) {
|
|
528
|
+
const diferenca = aridade - argumentos.length;
|
|
529
|
+
for (let i = 0; i < diferenca; i++) {
|
|
530
|
+
argumentos.push(null);
|
|
531
|
+
}
|
|
532
|
+
} /* else {
|
|
533
|
+
// TODO: Aparentemente isso aqui nunca funcionou.
|
|
534
|
+
// Avaliar de simplesmente apagar este código, e usar o que foi
|
|
535
|
+
// implementado em `DeleguaFuncao.chamar`.
|
|
536
|
+
if (
|
|
537
|
+
parametros &&
|
|
538
|
+
parametros.length > 0 &&
|
|
539
|
+
parametros[parametros.length - 1].abrangencia === 'multiplo'
|
|
540
|
+
) {
|
|
541
|
+
let novosArgumentos = argumentos.slice(0, parametros.length - 1);
|
|
542
|
+
novosArgumentos = novosArgumentos.concat(
|
|
543
|
+
argumentos.slice(parametros.length - 1, argumentos.length)
|
|
544
|
+
);
|
|
545
|
+
argumentos = novosArgumentos;
|
|
546
|
+
}
|
|
547
|
+
} */
|
|
548
|
+
if (entidadeChamada instanceof estruturas_1.FuncaoPadrao) {
|
|
549
|
+
try {
|
|
550
|
+
return entidadeChamada.chamar(this, argumentos.map((a) => a && a.valor && a.valor.hasOwnProperty('valor') ? a.valor.valor : a === null || a === void 0 ? void 0 : a.valor), expressao.entidadeChamada.simbolo);
|
|
551
|
+
}
|
|
552
|
+
catch (erro) {
|
|
553
|
+
this.erros.push({
|
|
554
|
+
erroInterno: erro,
|
|
555
|
+
linha: expressao.linha,
|
|
556
|
+
hashArquivo: expressao.hashArquivo,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Por algum motivo misterioso, `entidadeChamada instanceof Chamavel` dá `false` em Liquido,
|
|
561
|
+
// mesmo que esteja tudo certo com `DeleguaFuncao`,
|
|
562
|
+
// então precisamos testar o nome do construtor também.
|
|
563
|
+
if (entidadeChamada instanceof estruturas_1.Chamavel || entidadeChamada.constructor.name === 'DeleguaFuncao') {
|
|
564
|
+
const retornoEntidadeChamada = await entidadeChamada.chamar(this, argumentos);
|
|
565
|
+
return retornoEntidadeChamada;
|
|
566
|
+
}
|
|
567
|
+
// A função chamada pode ser de uma biblioteca JavaScript.
|
|
568
|
+
// Neste caso apenas testamos se o tipo é uma função.
|
|
569
|
+
// TODO: Descobrir qual caso exatamente passa aqui.
|
|
570
|
+
if (typeof entidadeChamada === primitivos_1.default.FUNCAO) {
|
|
571
|
+
let objeto = null;
|
|
572
|
+
if (expressao.entidadeChamada.objeto) {
|
|
573
|
+
objeto = await this.avaliar(expressao.entidadeChamada.objeto);
|
|
574
|
+
}
|
|
575
|
+
return entidadeChamada.apply(objeto.hasOwnProperty('valor') ? objeto.valor : objeto, argumentos);
|
|
576
|
+
}
|
|
577
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.parentese, 'Só pode chamar função ou classe.', expressao.linha));
|
|
578
|
+
}
|
|
579
|
+
catch (erro) {
|
|
580
|
+
this.erros.push({
|
|
581
|
+
erroInterno: erro,
|
|
582
|
+
linha: expressao.linha,
|
|
583
|
+
hashArquivo: expressao.hashArquivo,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Execução de uma expressão de atribuição.
|
|
589
|
+
* @param expressao A expressão.
|
|
590
|
+
* @returns O valor atribuído.
|
|
591
|
+
*/
|
|
592
|
+
async visitarExpressaoDeAtribuicao(expressao) {
|
|
593
|
+
const valor = await this.avaliar(expressao.valor);
|
|
594
|
+
const valorResolvido = valor !== undefined && valor.hasOwnProperty('valor') ? valor.valor : valor;
|
|
595
|
+
let indice = null;
|
|
596
|
+
if (expressao.indice) {
|
|
597
|
+
indice = await this.avaliar(expressao.indice);
|
|
598
|
+
}
|
|
599
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.simbolo, valorResolvido, indice);
|
|
600
|
+
return valorResolvido;
|
|
601
|
+
}
|
|
602
|
+
procurarVariavel(simbolo) {
|
|
603
|
+
return this.pilhaEscoposExecucao.obterValorVariavel(simbolo);
|
|
604
|
+
}
|
|
605
|
+
visitarExpressaoDeVariavel(expressao) {
|
|
606
|
+
return this.procurarVariavel(expressao.simbolo);
|
|
607
|
+
}
|
|
608
|
+
async visitarDeclaracaoDeExpressao(declaracao) {
|
|
609
|
+
return await this.avaliar(declaracao.expressao);
|
|
610
|
+
}
|
|
611
|
+
async visitarExpressaoLogica(expressao) {
|
|
612
|
+
const esquerda = await this.avaliar(expressao.esquerda);
|
|
613
|
+
if (expressao.operador.tipo === delegua_1.default.EM) {
|
|
614
|
+
const direita = await this.avaliar(expressao.direita);
|
|
615
|
+
if (Array.isArray(direita) || typeof direita === primitivos_1.default.TEXTO) {
|
|
616
|
+
return direita.includes(esquerda);
|
|
617
|
+
}
|
|
618
|
+
else if (direita.constructor === Object) {
|
|
619
|
+
return esquerda in direita;
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(esquerda, "Tipo de chamada inválida com 'em'.", expressao.linha);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
// se um estado for verdadeiro, retorna verdadeiro
|
|
626
|
+
if (expressao.operador.tipo === delegua_1.default.OU) {
|
|
627
|
+
if (this.eVerdadeiro(esquerda))
|
|
628
|
+
return esquerda;
|
|
629
|
+
}
|
|
630
|
+
// se um estado for falso, retorna falso
|
|
631
|
+
if (expressao.operador.tipo === delegua_1.default.E) {
|
|
632
|
+
if (!this.eVerdadeiro(esquerda))
|
|
633
|
+
return esquerda;
|
|
634
|
+
}
|
|
635
|
+
return await this.avaliar(expressao.direita);
|
|
636
|
+
}
|
|
637
|
+
async visitarDeclaracaoPara(declaracao) {
|
|
638
|
+
const declaracaoInicializador = Array.isArray(declaracao.inicializador)
|
|
639
|
+
? declaracao.inicializador[0]
|
|
640
|
+
: declaracao.inicializador;
|
|
641
|
+
if (declaracaoInicializador !== null) {
|
|
642
|
+
await this.avaliar(declaracaoInicializador);
|
|
643
|
+
}
|
|
644
|
+
let retornoExecucao;
|
|
645
|
+
while (!(retornoExecucao instanceof quebras_1.Quebra)) {
|
|
646
|
+
if (declaracao.condicao !== null && !this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
retornoExecucao = await this.executar(declaracao.corpo);
|
|
651
|
+
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
655
|
+
retornoExecucao = null;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
catch (erro) {
|
|
659
|
+
this.erros.push({
|
|
660
|
+
erroInterno: erro,
|
|
661
|
+
linha: declaracao.linha,
|
|
662
|
+
hashArquivo: declaracao.hashArquivo,
|
|
663
|
+
});
|
|
664
|
+
return Promise.reject(erro);
|
|
665
|
+
}
|
|
666
|
+
if (declaracao.incrementar !== null) {
|
|
667
|
+
await this.avaliar(declaracao.incrementar);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return retornoExecucao;
|
|
671
|
+
}
|
|
672
|
+
async visitarDeclaracaoParaCada(declaracao) {
|
|
673
|
+
let retornoExecucao;
|
|
674
|
+
const vetorResolvido = await this.avaliar(declaracao.vetor);
|
|
675
|
+
const valorVetorResolvido = vetorResolvido.hasOwnProperty('valor') ? vetorResolvido.valor : vetorResolvido;
|
|
676
|
+
if (!Array.isArray(valorVetorResolvido)) {
|
|
677
|
+
return Promise.reject("Variável ou literal provida em instrução 'para cada' não é um vetor.");
|
|
678
|
+
}
|
|
679
|
+
while (!(retornoExecucao instanceof quebras_1.Quebra) && declaracao.posicaoAtual < valorVetorResolvido.length) {
|
|
680
|
+
try {
|
|
681
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.nomeVariavelIteracao, valorVetorResolvido[declaracao.posicaoAtual]);
|
|
682
|
+
retornoExecucao = await this.executar(declaracao.corpo);
|
|
683
|
+
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
687
|
+
retornoExecucao = null;
|
|
688
|
+
}
|
|
689
|
+
declaracao.posicaoAtual++;
|
|
690
|
+
}
|
|
691
|
+
catch (erro) {
|
|
692
|
+
this.erros.push({
|
|
693
|
+
erroInterno: erro,
|
|
694
|
+
linha: declaracao.linha,
|
|
695
|
+
hashArquivo: declaracao.hashArquivo,
|
|
696
|
+
});
|
|
697
|
+
return Promise.reject(erro);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return retornoExecucao;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Executa uma expressão Se, que tem uma condição, pode ter um bloco
|
|
704
|
+
* Senão, e múltiplos blocos Senão-se.
|
|
705
|
+
* @param declaracao A declaração Se.
|
|
706
|
+
* @returns O resultado da avaliação do bloco cuja condição é verdadeira.
|
|
707
|
+
*/
|
|
708
|
+
async visitarDeclaracaoSe(declaracao) {
|
|
709
|
+
if (this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
710
|
+
return await this.executar(declaracao.caminhoEntao);
|
|
711
|
+
}
|
|
712
|
+
for (let i = 0; i < declaracao.caminhosSeSenao.length; i++) {
|
|
713
|
+
const atual = declaracao.caminhosSeSenao[i];
|
|
714
|
+
if (this.eVerdadeiro(await this.avaliar(atual.condicao))) {
|
|
715
|
+
return await this.executar(atual.caminho);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (declaracao.caminhoSenao !== null) {
|
|
719
|
+
return await this.executar(declaracao.caminhoSenao);
|
|
720
|
+
}
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
async visitarDeclaracaoEnquanto(declaracao) {
|
|
724
|
+
let retornoExecucao;
|
|
725
|
+
while (!(retornoExecucao instanceof quebras_1.Quebra) && this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
|
|
726
|
+
try {
|
|
727
|
+
retornoExecucao = await this.executar(declaracao.corpo);
|
|
728
|
+
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
732
|
+
retornoExecucao = null;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
catch (erro) {
|
|
736
|
+
this.erros.push({
|
|
737
|
+
erroInterno: erro,
|
|
738
|
+
linha: declaracao.linha,
|
|
739
|
+
hashArquivo: declaracao.hashArquivo,
|
|
740
|
+
});
|
|
741
|
+
return Promise.reject(erro);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
return retornoExecucao;
|
|
745
|
+
}
|
|
746
|
+
async visitarDeclaracaoEscolha(declaracao) {
|
|
747
|
+
const condicaoEscolha = await this.avaliar(declaracao.identificadorOuLiteral);
|
|
748
|
+
const valorCondicaoEscolha = condicaoEscolha.hasOwnProperty('valor') ? condicaoEscolha.valor : condicaoEscolha;
|
|
749
|
+
const caminhos = declaracao.caminhos;
|
|
750
|
+
const caminhoPadrao = declaracao.caminhoPadrao;
|
|
751
|
+
let encontrado = false;
|
|
752
|
+
try {
|
|
753
|
+
for (let i = 0; i < caminhos.length; i++) {
|
|
754
|
+
const caminho = caminhos[i];
|
|
755
|
+
for (let j = 0; j < caminho.condicoes.length; j++) {
|
|
756
|
+
const condicaoAvaliada = await this.avaliar(caminho.condicoes[j]);
|
|
757
|
+
if (condicaoAvaliada === valorCondicaoEscolha) {
|
|
758
|
+
encontrado = true;
|
|
759
|
+
try {
|
|
760
|
+
await this.executarBloco(caminho.declaracoes);
|
|
761
|
+
}
|
|
762
|
+
catch (erro) {
|
|
763
|
+
this.erros.push({
|
|
764
|
+
erroInterno: erro,
|
|
765
|
+
linha: declaracao.linha,
|
|
766
|
+
hashArquivo: declaracao.hashArquivo,
|
|
767
|
+
});
|
|
768
|
+
return Promise.reject(erro);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (caminhoPadrao !== null && !encontrado) {
|
|
774
|
+
await this.executarBloco(caminhoPadrao.declaracoes);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
catch (erro) {
|
|
778
|
+
this.erros.push({
|
|
779
|
+
erroInterno: erro,
|
|
780
|
+
linha: declaracao.linha,
|
|
781
|
+
hashArquivo: declaracao.hashArquivo,
|
|
782
|
+
});
|
|
783
|
+
throw erro;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
async visitarDeclaracaoFazer(declaracao) {
|
|
787
|
+
let retornoExecucao;
|
|
788
|
+
do {
|
|
789
|
+
try {
|
|
790
|
+
retornoExecucao = await this.executar(declaracao.caminhoFazer);
|
|
791
|
+
if (retornoExecucao instanceof quebras_1.SustarQuebra) {
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
if (retornoExecucao instanceof quebras_1.ContinuarQuebra) {
|
|
795
|
+
retornoExecucao = null;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
catch (erro) {
|
|
799
|
+
this.erros.push({
|
|
800
|
+
erroInterno: erro,
|
|
801
|
+
linha: declaracao.linha,
|
|
802
|
+
hashArquivo: declaracao.hashArquivo,
|
|
803
|
+
});
|
|
804
|
+
return Promise.reject(erro);
|
|
805
|
+
}
|
|
806
|
+
} while (!(retornoExecucao instanceof quebras_1.Quebra) &&
|
|
807
|
+
this.eVerdadeiro(await this.avaliar(declaracao.condicaoEnquanto)));
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Interpretação de uma declaração `tente`.
|
|
811
|
+
* @param declaracao O objeto da declaração.
|
|
812
|
+
*/
|
|
813
|
+
async visitarDeclaracaoTente(declaracao) {
|
|
814
|
+
let valorRetorno;
|
|
815
|
+
try {
|
|
816
|
+
this.emDeclaracaoTente = true;
|
|
817
|
+
try {
|
|
818
|
+
valorRetorno = await this.executarBloco(declaracao.caminhoTente);
|
|
819
|
+
}
|
|
820
|
+
catch (erro) {
|
|
821
|
+
if (declaracao.caminhoPegue !== null) {
|
|
822
|
+
// `caminhoPegue` aqui pode ser um construto de função (se `pegue` tem parâmetros)
|
|
823
|
+
// ou um vetor de `Declaracao` (`pegue` sem parâmetros).
|
|
824
|
+
// As execuções, portanto, são diferentes.
|
|
825
|
+
if (Array.isArray(declaracao.caminhoPegue)) {
|
|
826
|
+
valorRetorno = await this.executarBloco(declaracao.caminhoPegue);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
const literalErro = new construtos_1.Literal(declaracao.hashArquivo, Number(declaracao.linha), erro.mensagem);
|
|
830
|
+
const chamadaPegue = new construtos_1.Chamada(declaracao.caminhoPegue.hashArquivo, declaracao.caminhoPegue, null, [literalErro]);
|
|
831
|
+
valorRetorno = await chamadaPegue.aceitar(this);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
finally {
|
|
837
|
+
if (declaracao.caminhoFinalmente !== null)
|
|
838
|
+
valorRetorno = await this.executarBloco(declaracao.caminhoFinalmente);
|
|
839
|
+
this.emDeclaracaoTente = false;
|
|
840
|
+
}
|
|
841
|
+
return valorRetorno;
|
|
842
|
+
}
|
|
843
|
+
async visitarDeclaracaoImportar(declaracao) {
|
|
844
|
+
return Promise.reject('Importação de arquivos não suportada por Interpretador Base.');
|
|
845
|
+
}
|
|
846
|
+
async avaliarArgumentosEscreva(argumentos) {
|
|
847
|
+
let formatoTexto = '';
|
|
848
|
+
for (const argumento of argumentos) {
|
|
849
|
+
const resultadoAvaliacao = await this.avaliar(argumento);
|
|
850
|
+
let valor = (resultadoAvaliacao === null || resultadoAvaliacao === void 0 ? void 0 : resultadoAvaliacao.hasOwnProperty('valor')) ? resultadoAvaliacao.valor : resultadoAvaliacao;
|
|
851
|
+
formatoTexto += `${this.paraTexto(valor)} `;
|
|
852
|
+
}
|
|
853
|
+
return formatoTexto.trimEnd();
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Execução de uma escrita na saída padrão, sem quebras de linha.
|
|
857
|
+
* Implementada para alguns dialetos, como VisuAlg.
|
|
858
|
+
* @param declaracao A declaração.
|
|
859
|
+
* @returns Sempre nulo, por convenção de visita.
|
|
860
|
+
*/
|
|
861
|
+
async visitarDeclaracaoEscrevaMesmaLinha(declaracao) {
|
|
862
|
+
try {
|
|
863
|
+
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
|
|
864
|
+
this.funcaoDeRetornoMesmaLinha(formatoTexto);
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
catch (erro) {
|
|
868
|
+
this.erros.push({
|
|
869
|
+
erroInterno: erro,
|
|
870
|
+
linha: declaracao.linha,
|
|
871
|
+
hashArquivo: declaracao.hashArquivo,
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Execução de uma escrita na saída configurada, que pode ser `console` (padrão) ou
|
|
877
|
+
* alguma função para escrever numa página Web.
|
|
878
|
+
* @param declaracao A declaração.
|
|
879
|
+
* @returns Sempre nulo, por convenção de visita.
|
|
880
|
+
*/
|
|
881
|
+
async visitarDeclaracaoEscreva(declaracao) {
|
|
882
|
+
try {
|
|
883
|
+
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
|
|
884
|
+
this.funcaoDeRetorno(formatoTexto);
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
catch (erro) {
|
|
888
|
+
this.erros.push({
|
|
889
|
+
erroInterno: erro,
|
|
890
|
+
linha: declaracao.linha,
|
|
891
|
+
hashArquivo: declaracao.hashArquivo,
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Empilha declarações na pilha de escopos de execução, cria um novo ambiente e
|
|
897
|
+
* executa as declarações empilhadas.
|
|
898
|
+
* Se o retorno do último bloco foi uma exceção (normalmente um erro em tempo de execução),
|
|
899
|
+
* atira a exceção daqui.
|
|
900
|
+
* Isso é usado, por exemplo, em blocos tente ... pegue ... finalmente.
|
|
901
|
+
* @param declaracoes Um vetor de declaracoes a ser executado.
|
|
902
|
+
* @param ambiente O ambiente de execução quando houver, como parâmetros, argumentos, etc.
|
|
903
|
+
*/
|
|
904
|
+
async executarBloco(declaracoes, ambiente) {
|
|
905
|
+
const escopoExecucao = {
|
|
906
|
+
declaracoes: declaracoes,
|
|
907
|
+
declaracaoAtual: 0,
|
|
908
|
+
ambiente: ambiente || new espaco_variaveis_1.EspacoVariaveis(),
|
|
909
|
+
finalizado: false,
|
|
910
|
+
tipo: 'outro',
|
|
911
|
+
emLacoRepeticao: false,
|
|
912
|
+
};
|
|
913
|
+
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
914
|
+
const retornoUltimoEscopo = await this.executarUltimoEscopo();
|
|
915
|
+
if (retornoUltimoEscopo instanceof excecoes_1.ErroEmTempoDeExecucao) {
|
|
916
|
+
return Promise.reject(retornoUltimoEscopo);
|
|
917
|
+
}
|
|
918
|
+
return retornoUltimoEscopo;
|
|
919
|
+
}
|
|
920
|
+
async visitarExpressaoBloco(declaracao) {
|
|
921
|
+
return await this.executarBloco(declaracao.declaracoes);
|
|
922
|
+
}
|
|
923
|
+
async avaliacaoDeclaracaoVarOuConst(declaracao) {
|
|
924
|
+
let valorOuOutraVariavel = null;
|
|
925
|
+
if (declaracao.inicializador !== null) {
|
|
926
|
+
valorOuOutraVariavel = await this.avaliar(declaracao.inicializador);
|
|
927
|
+
}
|
|
928
|
+
let valorFinal = null;
|
|
929
|
+
if (valorOuOutraVariavel !== null && valorOuOutraVariavel !== undefined) {
|
|
930
|
+
valorFinal = valorOuOutraVariavel.hasOwnProperty('valor')
|
|
931
|
+
? valorOuOutraVariavel.valor
|
|
932
|
+
: valorOuOutraVariavel;
|
|
933
|
+
}
|
|
934
|
+
return valorFinal;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Executa expressão de definição de constante.
|
|
938
|
+
* @param declaracao A declaração `Const`.
|
|
939
|
+
* @returns Sempre retorna nulo.
|
|
940
|
+
*/
|
|
941
|
+
async visitarDeclaracaoConst(declaracao) {
|
|
942
|
+
const valorFinal = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
943
|
+
this.pilhaEscoposExecucao.definirConstante(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Executa expressão de definição de múltiplas constantes.
|
|
948
|
+
* @param declaracao A declaração `ConstMultiplo`.
|
|
949
|
+
* @returns Sempre retorna nulo.
|
|
950
|
+
*/
|
|
951
|
+
async visitarDeclaracaoConstMultiplo(declaracao) {
|
|
952
|
+
const valoresFinais = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
953
|
+
for (let [indice, valor] of valoresFinais.entries()) {
|
|
954
|
+
this.pilhaEscoposExecucao.definirConstante(declaracao.simbolos[indice].lexema, valor, declaracao.tipo);
|
|
955
|
+
}
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
visitarExpressaoContinua(declaracao) {
|
|
959
|
+
return new quebras_1.ContinuarQuebra();
|
|
960
|
+
}
|
|
961
|
+
visitarExpressaoSustar(declaracao) {
|
|
962
|
+
return new quebras_1.SustarQuebra();
|
|
963
|
+
}
|
|
964
|
+
async visitarExpressaoRetornar(declaracao) {
|
|
965
|
+
let valor = null;
|
|
966
|
+
if (declaracao.valor != null)
|
|
967
|
+
valor = await this.avaliar(declaracao.valor);
|
|
968
|
+
return new quebras_1.RetornoQuebra(valor);
|
|
969
|
+
}
|
|
970
|
+
async visitarExpressaoDeleguaFuncao(corpoDeclaracao) {
|
|
971
|
+
return new estruturas_1.DeleguaFuncao(null, corpoDeclaracao);
|
|
972
|
+
}
|
|
973
|
+
async visitarExpressaoAtribuicaoPorIndice(expressao) {
|
|
974
|
+
const promises = await Promise.all([
|
|
975
|
+
this.avaliar(expressao.objeto),
|
|
976
|
+
this.avaliar(expressao.indice),
|
|
977
|
+
this.avaliar(expressao.valor),
|
|
978
|
+
]);
|
|
979
|
+
let objeto = promises[0];
|
|
980
|
+
let indice = promises[1];
|
|
981
|
+
const valor = promises[2];
|
|
982
|
+
if (objeto.tipo === delegua_2.default.TUPLA) {
|
|
983
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.objeto.simbolo.lexema, 'Não é possível modificar uma tupla. As tuplas são estruturas de dados imutáveis.', expressao.linha));
|
|
984
|
+
}
|
|
985
|
+
objeto = objeto.hasOwnProperty('valor') ? objeto.valor : objeto;
|
|
986
|
+
indice = indice.hasOwnProperty('valor') ? indice.valor : indice;
|
|
987
|
+
if (Array.isArray(objeto)) {
|
|
988
|
+
if (indice < 0 && objeto.length !== 0) {
|
|
989
|
+
while (indice < 0) {
|
|
990
|
+
indice += objeto.length;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
while (objeto.length < indice) {
|
|
994
|
+
objeto.push(null);
|
|
995
|
+
}
|
|
996
|
+
objeto[indice] = valor;
|
|
997
|
+
}
|
|
998
|
+
else if (objeto.constructor === Object ||
|
|
999
|
+
objeto instanceof estruturas_1.ObjetoDeleguaClasse ||
|
|
1000
|
+
objeto instanceof estruturas_1.DeleguaFuncao ||
|
|
1001
|
+
objeto instanceof estruturas_1.DescritorTipoClasse ||
|
|
1002
|
+
objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1003
|
+
objeto[indice] = valor;
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.objeto.nome, 'Somente listas, dicionários, classes e objetos podem ser mudados por sobrescrita.', expressao.linha));
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
async visitarExpressaoAcessoIndiceVariavel(expressao) {
|
|
1010
|
+
const promises = await Promise.all([this.avaliar(expressao.entidadeChamada), this.avaliar(expressao.indice)]);
|
|
1011
|
+
const variavelObjeto = promises[0];
|
|
1012
|
+
const indice = promises[1];
|
|
1013
|
+
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1014
|
+
let valorIndice = indice.hasOwnProperty('valor') ? indice.valor : indice;
|
|
1015
|
+
if (Array.isArray(objeto)) {
|
|
1016
|
+
if (!Number.isInteger(valorIndice)) {
|
|
1017
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Somente inteiros podem ser usados para indexar um vetor.', expressao.linha));
|
|
1018
|
+
}
|
|
1019
|
+
if (valorIndice < 0 && objeto.length !== 0) {
|
|
1020
|
+
while (valorIndice < 0) {
|
|
1021
|
+
valorIndice += objeto.length;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
if (valorIndice >= objeto.length) {
|
|
1025
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Índice do vetor fora do intervalo.', expressao.linha));
|
|
1026
|
+
}
|
|
1027
|
+
return objeto[valorIndice];
|
|
1028
|
+
}
|
|
1029
|
+
if (objeto instanceof construtos_1.Vetor) {
|
|
1030
|
+
return objeto.valores[valorIndice];
|
|
1031
|
+
}
|
|
1032
|
+
if (objeto.constructor === Object ||
|
|
1033
|
+
objeto instanceof estruturas_1.ObjetoDeleguaClasse ||
|
|
1034
|
+
objeto instanceof estruturas_1.DeleguaFuncao ||
|
|
1035
|
+
objeto instanceof estruturas_1.DescritorTipoClasse ||
|
|
1036
|
+
objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1037
|
+
return objeto[valorIndice] || null;
|
|
1038
|
+
}
|
|
1039
|
+
if (typeof objeto === primitivos_1.default.TEXTO) {
|
|
1040
|
+
if (!Number.isInteger(valorIndice)) {
|
|
1041
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Somente inteiros podem ser usados para indexar um vetor.', expressao.linha));
|
|
1042
|
+
}
|
|
1043
|
+
if (valorIndice < 0 && objeto.length !== 0) {
|
|
1044
|
+
while (valorIndice < 0) {
|
|
1045
|
+
valorIndice += objeto.length;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
if (valorIndice >= objeto.length) {
|
|
1049
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Índice fora do tamanho.', expressao.linha));
|
|
1050
|
+
}
|
|
1051
|
+
return objeto.charAt(valorIndice);
|
|
1052
|
+
}
|
|
1053
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.entidadeChamada.nome, 'Somente listas, dicionários, classes e objetos podem ter seus valores indexados.', expressao.linha));
|
|
1054
|
+
}
|
|
1055
|
+
async visitarExpressaoDefinirValor(expressao) {
|
|
1056
|
+
const variavelObjeto = await this.avaliar(expressao.objeto);
|
|
1057
|
+
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1058
|
+
if (objeto.constructor.name !== 'ObjetoDeleguaClasse' && objeto.constructor !== Object) {
|
|
1059
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.nome, 'Somente instâncias e dicionários podem possuir campos.', expressao.linha));
|
|
1060
|
+
}
|
|
1061
|
+
const valor = await this.avaliar(expressao.valor);
|
|
1062
|
+
if (objeto.constructor.name === 'ObjetoDeleguaClasse') {
|
|
1063
|
+
objeto.definir(expressao.nome, valor);
|
|
1064
|
+
return valor;
|
|
1065
|
+
}
|
|
1066
|
+
if (objeto.constructor === Object) {
|
|
1067
|
+
objeto[expressao.nome.lexema] = valor;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
visitarDeclaracaoDefinicaoFuncao(declaracao) {
|
|
1071
|
+
const funcao = new estruturas_1.DeleguaFuncao(declaracao.simbolo.lexema, declaracao.funcao);
|
|
1072
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, funcao);
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Executa uma declaração de classe.
|
|
1076
|
+
* Uma variável do tipo `DeleguaClasse` é adicionada à pilha de escopos de execução.
|
|
1077
|
+
* @param declaracao A declaração de classe.
|
|
1078
|
+
* @returns Sempre retorna nulo, por ser requerido pelo contrato de visita.
|
|
1079
|
+
*/
|
|
1080
|
+
async visitarDeclaracaoClasse(declaracao) {
|
|
1081
|
+
let superClasse = null;
|
|
1082
|
+
if (declaracao.superClasse !== null && declaracao.superClasse !== undefined) {
|
|
1083
|
+
const variavelSuperClasse = await this.avaliar(declaracao.superClasse);
|
|
1084
|
+
superClasse = variavelSuperClasse.valor;
|
|
1085
|
+
if (!(superClasse instanceof estruturas_1.DescritorTipoClasse)) {
|
|
1086
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(declaracao.superClasse.nome, 'Superclasse precisa ser uma classe.', declaracao.linha);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
// TODO: Precisamos disso?
|
|
1090
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, declaracao);
|
|
1091
|
+
if (declaracao.superClasse !== null && declaracao.superClasse !== undefined) {
|
|
1092
|
+
this.pilhaEscoposExecucao.definirVariavel('super', superClasse);
|
|
1093
|
+
}
|
|
1094
|
+
const metodos = {};
|
|
1095
|
+
const definirMetodos = declaracao.metodos;
|
|
1096
|
+
for (let i = 0; i < declaracao.metodos.length; i++) {
|
|
1097
|
+
const metodoAtual = definirMetodos[i];
|
|
1098
|
+
const eInicializador = metodoAtual.simbolo.lexema === 'construtor';
|
|
1099
|
+
const funcao = new estruturas_1.DeleguaFuncao(metodoAtual.simbolo.lexema, metodoAtual.funcao, undefined, eInicializador);
|
|
1100
|
+
metodos[metodoAtual.simbolo.lexema] = funcao;
|
|
1101
|
+
}
|
|
1102
|
+
const descritorTipoClasse = new estruturas_1.DescritorTipoClasse(declaracao.simbolo, superClasse, metodos, declaracao.propriedades);
|
|
1103
|
+
descritorTipoClasse.dialetoRequerExpansaoPropriedadesEspacoVariaveis =
|
|
1104
|
+
this.expandirPropriedadesDeObjetosEmEspacoVariaveis;
|
|
1105
|
+
descritorTipoClasse.dialetoRequerDeclaracaoPropriedades = this.requerDeclaracaoPropriedades;
|
|
1106
|
+
// TODO: Recolocar isso se for necessário.
|
|
1107
|
+
/* if (superClasse !== null) {
|
|
1108
|
+
this.ambiente = this.ambiente.enclosing;
|
|
1109
|
+
} */
|
|
1110
|
+
this.pilhaEscoposExecucao.atribuirVariavel(declaracao.simbolo, descritorTipoClasse);
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Executa um acesso a método, normalmente de um objeto de classe.
|
|
1115
|
+
* @param {AcessoMetodoOuPropriedade} expressao A expressão de acesso.
|
|
1116
|
+
* @returns O resultado da execução.
|
|
1117
|
+
*/
|
|
1118
|
+
async visitarExpressaoAcessoMetodo(expressao) {
|
|
1119
|
+
let variavelObjeto = await this.avaliar(expressao.objeto);
|
|
1120
|
+
// Este caso acontece quando há encadeamento de métodos.
|
|
1121
|
+
// Por exemplo, `objeto1.metodo1().metodo2()`.
|
|
1122
|
+
// Como `RetornoQuebra` também possui `valor`, precisamos extrair o
|
|
1123
|
+
// valor dele primeiro.
|
|
1124
|
+
if (variavelObjeto.constructor.name === 'RetornoQuebra') {
|
|
1125
|
+
variavelObjeto = variavelObjeto.valor;
|
|
1126
|
+
}
|
|
1127
|
+
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
|
|
1128
|
+
// Outro caso que `instanceof` simplesmente não funciona para casos em Liquido,
|
|
1129
|
+
// então testamos também o nome do construtor.
|
|
1130
|
+
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto.constructor.name === 'ObjetoDeleguaClasse') {
|
|
1131
|
+
return objeto.obter(expressao.simbolo) || null;
|
|
1132
|
+
}
|
|
1133
|
+
// Objeto simples do JavaScript, ou dicionário de Delégua.
|
|
1134
|
+
if (objeto.constructor === Object) {
|
|
1135
|
+
const metodoDePrimitivaDicionario = primitivas_dicionario_1.default[expressao.simbolo.lexema];
|
|
1136
|
+
if (metodoDePrimitivaDicionario) {
|
|
1137
|
+
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaDicionario);
|
|
1138
|
+
}
|
|
1139
|
+
return objeto[expressao.simbolo.lexema] || null;
|
|
1140
|
+
}
|
|
1141
|
+
// Casos em que o objeto possui algum outro tipo que não o de objeto simples.
|
|
1142
|
+
// Normalmente executam quando uma biblioteca é importada, e estamos tentando
|
|
1143
|
+
// obter alguma propriedade ou método desse objeto.
|
|
1144
|
+
// Caso 1: Função tradicional do JavaScript.
|
|
1145
|
+
if (typeof objeto[expressao.simbolo.lexema] === primitivos_1.default.FUNCAO) {
|
|
1146
|
+
return objeto[expressao.simbolo.lexema];
|
|
1147
|
+
}
|
|
1148
|
+
// Caso 2: Objeto tradicional do JavaScript.
|
|
1149
|
+
if (typeof objeto[expressao.simbolo.lexema] === primitivos_1.default.OBJETO) {
|
|
1150
|
+
return objeto[expressao.simbolo.lexema];
|
|
1151
|
+
}
|
|
1152
|
+
// A partir daqui, presume-se que o objeto é uma das estruturas
|
|
1153
|
+
// de Delégua.
|
|
1154
|
+
if (objeto instanceof estruturas_1.DeleguaModulo) {
|
|
1155
|
+
return objeto.componentes[expressao.simbolo.lexema] || null;
|
|
1156
|
+
}
|
|
1157
|
+
let tipoObjeto = variavelObjeto.tipo;
|
|
1158
|
+
if (tipoObjeto === null || tipoObjeto === undefined) {
|
|
1159
|
+
tipoObjeto = (0, inferenciador_1.inferirTipoVariavel)(variavelObjeto);
|
|
1160
|
+
}
|
|
1161
|
+
// Como internamente um dicionário de Delégua é simplesmente um objeto de
|
|
1162
|
+
// JavaScript, as primitivas de dicionário, especificamente, são tratadas
|
|
1163
|
+
// mais acima.
|
|
1164
|
+
switch (tipoObjeto) {
|
|
1165
|
+
case delegua_2.default.INTEIRO:
|
|
1166
|
+
case delegua_2.default.NUMERO:
|
|
1167
|
+
case delegua_2.default.NÚMERO:
|
|
1168
|
+
const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.simbolo.lexema];
|
|
1169
|
+
if (metodoDePrimitivaNumero) {
|
|
1170
|
+
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaNumero);
|
|
1171
|
+
}
|
|
1172
|
+
break;
|
|
1173
|
+
case delegua_2.default.TEXTO:
|
|
1174
|
+
const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.simbolo.lexema];
|
|
1175
|
+
if (metodoDePrimitivaTexto) {
|
|
1176
|
+
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaTexto);
|
|
1177
|
+
}
|
|
1178
|
+
break;
|
|
1179
|
+
case delegua_2.default.VETOR:
|
|
1180
|
+
const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.simbolo.lexema];
|
|
1181
|
+
if (metodoDePrimitivaVetor) {
|
|
1182
|
+
return new metodo_primitiva_1.MetodoPrimitiva(objeto, metodoDePrimitivaVetor);
|
|
1183
|
+
}
|
|
1184
|
+
break;
|
|
1185
|
+
}
|
|
1186
|
+
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método para objeto ou primitiva não encontrado: ${expressao.simbolo.lexema}.`, expressao.linha));
|
|
1187
|
+
}
|
|
1188
|
+
visitarExpressaoIsto(expressao) {
|
|
1189
|
+
return this.procurarVariavel(expressao.palavraChave);
|
|
1190
|
+
}
|
|
1191
|
+
visitarDeclaracaoAleatorio(declaracao) {
|
|
1192
|
+
return Promise.resolve();
|
|
1193
|
+
}
|
|
1194
|
+
async visitarExpressaoDicionario(expressao) {
|
|
1195
|
+
const dicionario = {};
|
|
1196
|
+
for (let i = 0; i < expressao.chaves.length; i++) {
|
|
1197
|
+
const promises = await Promise.all([this.avaliar(expressao.chaves[i]), this.avaliar(expressao.valores[i])]);
|
|
1198
|
+
dicionario[promises[0]] = promises[1];
|
|
1199
|
+
}
|
|
1200
|
+
return dicionario;
|
|
1201
|
+
}
|
|
1202
|
+
async visitarExpressaoVetor(expressao) {
|
|
1203
|
+
const valores = [];
|
|
1204
|
+
for (let i = 0; i < expressao.valores.length; i++) {
|
|
1205
|
+
valores.push(await this.avaliar(expressao.valores[i]));
|
|
1206
|
+
}
|
|
1207
|
+
return valores;
|
|
1208
|
+
}
|
|
1209
|
+
visitarExpressaoSuper(expressao) {
|
|
1210
|
+
const superClasse = this.pilhaEscoposExecucao.obterVariavelPorNome('super');
|
|
1211
|
+
const objeto = this.pilhaEscoposExecucao.obterVariavelPorNome('isto');
|
|
1212
|
+
const metodo = superClasse.valor.encontrarMetodo(expressao.metodo.lexema);
|
|
1213
|
+
if (metodo === undefined) {
|
|
1214
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.metodo, 'Método chamado indefinido.', expressao.linha);
|
|
1215
|
+
}
|
|
1216
|
+
metodo.instancia = objeto.valor;
|
|
1217
|
+
return metodo;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Executa expressão de definição de variável.
|
|
1221
|
+
* @param declaracao A declaração Var
|
|
1222
|
+
* @returns Sempre retorna nulo.
|
|
1223
|
+
*/
|
|
1224
|
+
async visitarDeclaracaoVar(declaracao) {
|
|
1225
|
+
const valorFinal = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
1226
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Executa expressão de definição de múltiplas variáveis.
|
|
1231
|
+
* @param declaracao A declaração `VarMultiplo`.
|
|
1232
|
+
* @returns Sempre retorna nulo.
|
|
1233
|
+
*/
|
|
1234
|
+
async visitarDeclaracaoVarMultiplo(declaracao) {
|
|
1235
|
+
const valoresFinais = await this.avaliacaoDeclaracaoVarOuConst(declaracao);
|
|
1236
|
+
for (let [indice, valor] of valoresFinais.entries()) {
|
|
1237
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolos[indice].lexema, valor, declaracao.tipo);
|
|
1238
|
+
}
|
|
1239
|
+
return null;
|
|
1240
|
+
}
|
|
1241
|
+
paraTexto(objeto) {
|
|
1242
|
+
if (objeto === null || objeto === undefined)
|
|
1243
|
+
return delegua_2.default.NULO;
|
|
1244
|
+
if (typeof objeto === primitivos_1.default.BOOLEANO) {
|
|
1245
|
+
return objeto ? 'verdadeiro' : 'falso';
|
|
1246
|
+
}
|
|
1247
|
+
if (objeto instanceof quebras_1.RetornoQuebra) {
|
|
1248
|
+
if (typeof objeto.valor === 'boolean')
|
|
1249
|
+
return objeto.valor ? 'verdadeiro' : 'falso';
|
|
1250
|
+
}
|
|
1251
|
+
if (objeto instanceof Date) {
|
|
1252
|
+
const formato = Intl.DateTimeFormat('pt', {
|
|
1253
|
+
dateStyle: 'full',
|
|
1254
|
+
timeStyle: 'full',
|
|
1255
|
+
});
|
|
1256
|
+
return formato.format(objeto);
|
|
1257
|
+
}
|
|
1258
|
+
if (Array.isArray(objeto)) {
|
|
1259
|
+
let retornoVetor = '[';
|
|
1260
|
+
for (let elemento of objeto) {
|
|
1261
|
+
retornoVetor += typeof elemento === 'string' ? `'${elemento}', ` : `${this.paraTexto(elemento)}, `;
|
|
1262
|
+
}
|
|
1263
|
+
if (retornoVetor.length > 1) {
|
|
1264
|
+
retornoVetor = retornoVetor.slice(0, -2);
|
|
1265
|
+
}
|
|
1266
|
+
retornoVetor += ']';
|
|
1267
|
+
return retornoVetor;
|
|
1268
|
+
}
|
|
1269
|
+
if (objeto.valor instanceof estruturas_1.ObjetoPadrao)
|
|
1270
|
+
return objeto.valor.paraTexto();
|
|
1271
|
+
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto instanceof estruturas_1.DeleguaFuncao)
|
|
1272
|
+
return objeto.paraTexto();
|
|
1273
|
+
switch (objeto.constructor.name) {
|
|
1274
|
+
case 'Object':
|
|
1275
|
+
if ('tipo' in objeto) {
|
|
1276
|
+
switch (objeto.tipo) {
|
|
1277
|
+
case 'dicionário':
|
|
1278
|
+
return JSON.stringify(objeto.valor);
|
|
1279
|
+
default:
|
|
1280
|
+
return objeto.valor;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
if (typeof objeto === primitivos_1.default.OBJETO) {
|
|
1285
|
+
for (const obj in objeto) {
|
|
1286
|
+
let valor = objeto[obj];
|
|
1287
|
+
if (typeof valor === primitivos_1.default.BOOLEANO) {
|
|
1288
|
+
valor = valor ? 'verdadeiro' : 'falso';
|
|
1289
|
+
objeto[obj] = valor;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return JSON.stringify(objeto);
|
|
1293
|
+
}
|
|
1294
|
+
return objeto.toString();
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Efetivamente executa uma declaração.
|
|
1298
|
+
* @param declaracao A declaração a ser executada.
|
|
1299
|
+
* @param mostrarResultado Se resultado deve ser mostrado ou não. Normalmente usado
|
|
1300
|
+
* pelo modo LAIR.
|
|
1301
|
+
*/
|
|
1302
|
+
async executar(declaracao, mostrarResultado = false) {
|
|
1303
|
+
const resultado = await declaracao.aceitar(this);
|
|
1304
|
+
/* console.log("Resultado aceitar: " + resultado, this); */
|
|
1305
|
+
if (mostrarResultado) {
|
|
1306
|
+
this.funcaoDeRetorno(this.paraTexto(resultado));
|
|
1307
|
+
}
|
|
1308
|
+
if (resultado || typeof resultado === primitivos_1.default.BOOLEANO) {
|
|
1309
|
+
this.resultadoInterpretador.push(this.paraTexto(resultado));
|
|
1310
|
+
}
|
|
1311
|
+
return resultado;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Executa o último escopo empilhado no topo na pilha de escopos do interpretador.
|
|
1315
|
+
* Esse método pega exceções, mas apenas as devolve.
|
|
1316
|
+
*
|
|
1317
|
+
* O tratamento das exceções é feito de acordo com o bloco chamador.
|
|
1318
|
+
* Por exemplo, em `tente ... pegue ... finalmente`, a exceção é capturada e tratada.
|
|
1319
|
+
* Em outros blocos, pode ser desejável ter o erro em tela.
|
|
1320
|
+
* @param manterAmbiente Se verdadeiro, ambiente do topo da pilha de escopo é copiado para o ambiente imediatamente abaixo.
|
|
1321
|
+
* @returns O resultado da execução do escopo, se houver.
|
|
1322
|
+
*/
|
|
1323
|
+
async executarUltimoEscopo(manterAmbiente = false) {
|
|
1324
|
+
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
1325
|
+
try {
|
|
1326
|
+
let retornoExecucao;
|
|
1327
|
+
for (; !(retornoExecucao instanceof quebras_1.Quebra) && ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length; ultimoEscopo.declaracaoAtual++) {
|
|
1328
|
+
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
|
|
1329
|
+
}
|
|
1330
|
+
return retornoExecucao;
|
|
1331
|
+
}
|
|
1332
|
+
catch (erro) {
|
|
1333
|
+
const declaracaoAtual = ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual];
|
|
1334
|
+
if (!this.emDeclaracaoTente) {
|
|
1335
|
+
this.erros.push({
|
|
1336
|
+
erroInterno: erro,
|
|
1337
|
+
linha: declaracaoAtual.linha,
|
|
1338
|
+
hashArquivo: declaracaoAtual.hashArquivo,
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
return Promise.reject(erro);
|
|
1342
|
+
}
|
|
1343
|
+
finally {
|
|
1344
|
+
this.pilhaEscoposExecucao.removerUltimo();
|
|
1345
|
+
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
1346
|
+
if (manterAmbiente) {
|
|
1347
|
+
escopoAnterior.ambiente.valores = Object.assign(escopoAnterior.ambiente.valores, ultimoEscopo.ambiente.valores);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Interpretação sem depurador, com medição de performance.
|
|
1353
|
+
* Método que efetivamente inicia o processo de interpretação.
|
|
1354
|
+
* @param declaracoes Um vetor de declarações gerado pelo Avaliador Sintático.
|
|
1355
|
+
* @param manterAmbiente Se ambiente de execução (variáveis, classes, etc.) deve ser mantido. Normalmente usado
|
|
1356
|
+
* pelo modo REPL (LAIR).
|
|
1357
|
+
* @returns Um objeto com o resultado da interpretação.
|
|
1358
|
+
*/
|
|
1359
|
+
async interpretar(declaracoes, manterAmbiente = false) {
|
|
1360
|
+
this.erros = [];
|
|
1361
|
+
this.emDeclaracaoTente = false;
|
|
1362
|
+
const escopoExecucao = {
|
|
1363
|
+
declaracoes: declaracoes,
|
|
1364
|
+
declaracaoAtual: 0,
|
|
1365
|
+
ambiente: new espaco_variaveis_1.EspacoVariaveis(),
|
|
1366
|
+
finalizado: false,
|
|
1367
|
+
tipo: 'outro',
|
|
1368
|
+
emLacoRepeticao: false,
|
|
1369
|
+
};
|
|
1370
|
+
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
1371
|
+
const inicioInterpretacao = (0, browser_process_hrtime_1.default)();
|
|
1372
|
+
try {
|
|
1373
|
+
const retornoOuErro = await this.executarUltimoEscopo(manterAmbiente);
|
|
1374
|
+
if (retornoOuErro instanceof excecoes_1.ErroEmTempoDeExecucao) {
|
|
1375
|
+
this.erros.push(retornoOuErro);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
catch (erro) {
|
|
1379
|
+
this.erros.push({
|
|
1380
|
+
erroInterno: erro,
|
|
1381
|
+
linha: -1,
|
|
1382
|
+
hashArquivo: -1,
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
finally {
|
|
1386
|
+
if (this.performance) {
|
|
1387
|
+
const deltaInterpretacao = (0, browser_process_hrtime_1.default)(inicioInterpretacao);
|
|
1388
|
+
console.log(`[Interpretador] Tempo para interpretaçao: ${deltaInterpretacao[0] * 1e9 + deltaInterpretacao[1]}ns`);
|
|
1389
|
+
}
|
|
1390
|
+
const retorno = {
|
|
1391
|
+
erros: this.erros,
|
|
1392
|
+
resultado: this.resultadoInterpretador,
|
|
1393
|
+
};
|
|
1394
|
+
this.resultadoInterpretador = [];
|
|
1395
|
+
return retorno;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
exports.InterpretadorBase = InterpretadorBase;
|
|
1400
1400
|
//# sourceMappingURL=interpretador-base.js.map
|