NOTA DE ATUALIZAÇÃO PRISMA 1.0.107

1 - CORREÇÕES

1.1 Foi corrigida interceptação de erros, as mensagens de erro apresentam trace back (rastro de execução) normalmente.

1.2 Foi corrigido o acesso à tabela global _G (Estava com erro e inacessível em Prisma).

1.3 Foram melhorados os parâmetros de modo de abertura de arquivo na função es.abra('nome_arquivo', 'modo');

onde modo pode ser:

   Acresentados nomes curtos:
     l     : leitura
     lb    : leitura binária
     l+    : leitura e escrita
     l+b   : leitura e escrita binária
     e     : escrita
     eb    : escrita binária
     e+    : escrita e leitura
     e+b   : escrita e leitura binária
     a     : adição sem apagar o conteúdo atual do arquivo.
     a+    : leitura e adição de conteúdo sem apagar o conteúdo atual;
     a+b   : leitura e adição binária (sem apagar)
     
   Modos anteriores permanecem:
     leitura       : leitura
     leiturabin    : leitura binária
     leitura+bin   : leitura e escrita binária
     escrita       : escrita
     escritabin    : escrita binária
     escrita+bin   : escrita e leitura binária
     adicao        : adição de conteúdo sem apagar o conteúdo atual do arquivo.
     adição        : mesmo que o de cima com acentos
     adicaobin     : adição binária sem apagar o conteúdo
     adiçãobin     : mesmo de cima com acentos
     adicao+       : leitura e adição sem apagar o conteúdo
     adição+       : mesmo que o de cima com acentos
     adicao+bin    : leitura e adição binária sem apagar o conteúdo
     adição+bin    : mesmo de cima com acentos.
📋
 ex1.prisma
  1
  2
  3
  4
  5
  6
 local a, err = es.abra('arq.txt', 'lb'); //abre um arquivo em leitura binária
 se tipo(a) == 'arquivo' entao 
    imprima('arquivo aberto com sucesso') 
 senao  
    erro(err)
 fim

Os modos originais do inglês são permitidos: r, w, a, rb, wb, ab, r+, w+, a+, r+b, w+b, a+b

1.4 Corrigido o parâmetro da função pabra(arq, modo); (estava implementado incorretamente)

   modos aceitos:
       leitura    :  direciona a  saída do programa aberto para a entrada do programa atual prisma
       escrita    :  direciona a saída do programa atual prisma para a entrada do programa aberto
       
       Modos curtos aceitos:
           l : leitura
           e : escrita

1.5 Corrigida a função string.apare();

📋
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
//Teste string.apare();

local s = '   ola mundo!       ';
imprima( '>' .. string.apare(s) .. '<' );

s = '';//string vazia
imprima('>' .. s:apare() .. '<'); //podemos usar o método apare na própria string.

s = '              '; //string com somente espaços.
imprima('>' .. s:apare() .. '<' );
   Saída:
   
   >ola mundo!<
   ><
   ><

2 - Foi acrescentada a indexação de strings

E isso direto na VM para obter caractere a partir de um indice: s = 'abc'; imprima(s[1]) --> 'a';

Quando um indice é maior que o tamanho da string ou menor que 1, o retorno é uma string vazia, mesmo comportamento de string.corte();

Porém não é possível mudar o valor apenas obtê-lo:

📋
 
  1
   s[1] = 'A'; --> erro!

3 - Novas funções na biblioteca de base para verificação de tipos:

Obs.: *Os [, ...] - indica que aceita mais parâmetros opcionais.

É possível usar a função V() com tipos definidos pelo usuário, a partir do metamétodo __tipo();

📋
 ex.prisma
  1
  2
  3
local ret = retangulo:novo();
local ret2 = retangulo:novo();
V('retangulo', ret, ret2);

Obs.: caso o programador tenha definido o metamétodo __tipo() para retornar 'retangulo' dará certo, senão aparecerá uma mensagem de erro e o programa será finalizado.

Estas funções de tipo retornam o próprio valor ou valores se o tipo for correto ex.:

📋
 
  1
  2
  3
funcao somar(a,b)
  retorne N(a) + N(b); //caso a ou b não seja número, o programa é finalizado com erro.
fim

4 - Foi modificada a função tipo()

Agora ela aceita um metamétodo __tipo para retornar um tipo definido pelo usuário

📋
 
  1
  2
  3
  4
 local a,err = es.abra('file.txt', 'leitura'); 
 imprima(tipo(a)); //----> arquivo
 local meu_tipo = defmetatabela({}, { __tipo=funcao(este) retorne '<meu tipo>'; fim })
 imprima('tipo:', tipo(meu_tipo));//----> <meu tipo>

5 - Funcao escolha();

Semelhante ao switch de outras linguagens:

📋
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 local op = leia();
  local for = escolha(op);
  se for's' entao //único parâmetro é uma string, os parênteses são opcionais..
      imprima('saindo ...');
      sis.saia(0);
  senaose for'n' entao
      imprima('Usuário decidiu não sair ..\n');
  senao
      imprima('opção inválida ..\n');
  fim

Essa função é boa para situações em que temos que comparar um mesmo item várias vezes com menos repetição, veja o mesmo código abaixo sem usar a funcao escolha()

📋
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 local op = leia();
 se op == 's' entao
    imprima('saindo ...');
    sis.saia(0);
 senaose op == 'n' entao
     imprima('Usuário decidiu não sair ..\n');
 senao
     imprima('opção inválida ..\n');
 fim

A condição aceita qualquer valor e quantidade para ser comparado:

      se for(1,2,3,4,5) entao //mesmo que: se op==1 ou op==2 ou op==3 ou op==4 ou op==5 entao
          ...
      fim

6 - Acrescentados os operadores de bits 32 diretamente na maquina virtual Prisma.

   Nomes - operadores - exemplos
   bor:     |         i = 3 | 5;
   band:    &         a = 3 & 5;
   bxor:    ~         b = 3 ~ 5;
   lshift:  <<        c = 7 << 1;
   rshift:  >>        n = 7 >> 1;
   un. not: ~         n = ~7;

Para cada operador há um metamétodo:

         __bor, __band, __bxor, __bshl, __bshr, __bnot

7 - Adicionado o operador de divisão inteira, quando não precisamos da parte decimal:

         nome    -    operador    -    exemplo
         idiv            /.           imprima( 5 /. 2) //--> 2
 metamétodo:  __idiv

8 - Adicionado o metamétodo __tipo() para ser executado pela função tipo();

Exemplo:

📋
 
  1
  2
  3
  4
  5
  6
 local circ = {};
 local mt = {};
 mt.__tipo = funcao() retorne 'circulo'; fim
 
 defmetatabela( circ, mt);
 imprima(tipo(circ) ); //--> circulo

9 - Operador ternário

operador '?'

Uso: exp ? opcao1 ou opcao2

Exemplo:

 x = (n > 10) ? 1 ou n;

Obs.: Na verdade é um açúcar sintático para: x = (n > 10) e 1 ou n;

10 - Permitido o uso de palavras chaves e variáveis com acentos:

📋
 exemplo_acentos.prisma
  1
  2
  3
  4
  5
  6
  7
  8
  9
   local função máximo(...)
       local tn = {...};
       local atual=tn[1];
       para i=1, #tn início
      atual = (tn[i]>atual) ? tn[i] ou atual;
       fim
       retorne atual;
   fim       
   imprima( máximo(1,2,3,4,8,0,2,1,12,3,4,10,2,1,0) );//--> 12

As palavras sem acento ainda continuam compatíveis:

     funcao ou função são válidos, mas 'funçao' não é.
     entao ou então, senao ou senão, senaose ou senãose, ate ou até, nao ou não, inicio ou início etc.

Obs.: As variáveis da biblioteca padrão em Prisma continuam sem acento:

Exemplo: poe (e não põe) - mas é facilmente possível adicionar acentos: local põe = poe; por isso, decidi não mudar essa parte.

Obs.: Os retornos de tipos também continuam sem acentos: tipo(1); retorna numero e não número.

Obs.: A tabela corotina foi mudada para corrotina; em caso de necessidade atribua: corotina = corrotina;

11 - Nova função da biblioteca base: contador(inic, incr);

Cria uma função fecho(closure) e a retorna, esta função incrementa um valor a cada execução.

📋
 Exemplo:
  1
  2
  3
  4
  local cont = contador();
  imprima(cont() ); //-->1
  imprima(cont() ); //-->2
  imprima(cont() ); //-->3 e assim por diante.
📋
 podemos definir um valor inicial e um incremento:
  1
  2
  3
  4
  local cont = contador(0, 2);
  imprima( cont() ); //-->0
  imprima( cont() ); //-->2
  imprima( cont() ); //-->4 e assim por diante;
📋
 *podemos definir um decremento, ou seja, um valor que diminui a cada execução:
  1
  2
  3
  4
  local cont = contador(10,-1);
  imprima( cont() ); //--> 10
  imprima( cont() ); //--> 9
  imprima( cont() ); //--> 8 e assim por diante.

Obs.: observe que para o decremento apenas usamos um número negativo!

12 - Alteração na função sis.tamanho(); da biblioteca sis (sistema operacional)

Esta função recebia o nome de um arquivo e retornava o seu tamanho em bytes.

Agora ela pode também retornar o tamanho de um valor número C em bytes, bastando usar o caractere de escape % mais o caractere correspondente ao tipo numérico da linguagem C (dependente de plataforma):

📋
 exemplo:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
        
 local n = sis.tamanho('%i');  //sizeof(int);
 imprima(n);//--> 4
 imprima( sis.tamanho('%d'); //sizeof(int); --> 4 (%d ou %i são o mesmo valor);
 imprima( sis.tamanho('%f'); //sizeof(float); --> 4
 imprima( sis.tamanho('%lf'); //sizeof(double); --> 8
 imprima( sis.tamanho('%Lf'); //sizeof(long double); --> 16
 imprima( sis.tamanho('%lli'); //sizeof(long long int); --> 8
 imprima( sis.tamanho('%llu'); //sizeof(unsigned long long); --> 8
 imprima( sis.tamanho('%hi'); //sizeof(short int); --> 2
 imprima( sis.tamanho('%hu'); //sizeof(unsigned short); --> 2
 imprima( sis.tamanho('%p'); //sizeof(void *); --> 8
 imprima( sis.tamanho('%c'); //sizeof(char); --> 1

Pode retornar também verdadeiro ou falso para sistema big-endian e little-endian

📋
 endianess:
  1
  2
 imprima( sis.tamanho('%le')) //--> verdadeiro se o sistema for little-endian do contrário falso.
 imprima( sis.tamanho('%be')) //--> verdadeiro se o sistema for big-endian do contrário falso.

Obs.: geralmente o sistema é 'le' little-endian. Isso tem a ver com a ordem dos bytes que formam um número, pesquise por endianess in C

13 - Correções e alterações na biblioteca mat (matemática)

 *    ALTERAÇÕES: 
 * 
 *    ANTES  ------------>  DEPOIS
 * 
 *    mat.randonico()      mat.aleatorio()
 *    mat.xrandonico()     mat.xaleatorio()
 *    mat.arredonde()      mat.arredondeacima() //arredonda um número para cima. Ex.: 4.2 -> 5
 *    mat.corte()          mat.arredondeabaixo() //arredonda um número para baixo. Ex: 5.9 -> 5
 *    
 *    
 *    INCLUSÕES:
 * 
 *    mat.arredonde(n)  ----> arredonda um número para o valor inteiro mais próximo.  
 *                           Ex.:   5.9 --> 6;    5.2 --> 5
 *    mat.raizcubica(n)  ---> retorna a raiz cúbica de n    imprima(mat.raizcubica(1000) ); //-->10

Veja os exemplos:

📋
 Exemplo mat.:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
local n;

poe'---------------------------------------';
poe'Observe o primeiro aleatório, é igual sempre';
para i = 1, 9 inicio
    n = N(mat.aleatorio(1,10) ); //aleatorio entre um e dez.
    imprima(n);
fim
poe'---------------------------------------';
poe(
'Observe que segundo aleatorio é diferente a cada execução,',
'\npois usamos xaleatorio:'
)
//usando xaleatorio() para criar uma semente.

mat.xaleatorio(sis.tempo());//criando uma semente aleatória baseada no sis.tempo();
para i = 1, 9 inicio
    n = N(mat.aleatorio(1,10) ); //aleatorio entre um e dez.
    imprima(n);
fim

poe'\n---------------------------------------';
poe'---------------- mat.arredonde() -----------------';

imprima('3.8:', mat.arredonde(3.8) )
imprima('3.4', mat.arredonde(3.4) ); //a partir de 0.5 o número é arredondado para cima.

poe'\n---------------------------------------';
poe'---------------- mat.arredondeacima() -----------------';

imprima('3.1:', mat.arredondeacima(3.1) )

poe'\n---------------------------------------';
poe'---------------- mat.arredondeabaixo() -----------------';

imprima('3.8:', mat.arredondeabaixo(3.8) )


poe'\n---------------------------------------';
poe'---------------- mat.raizcubica(n) -----------------';

imprima('mat.raizcubica(27):', mat.raizcubica(27) )