meta.pris

Adalberto

24 nov 2023


Biblioteca para facilitar a manipulação de metatabelas e metamétodos. mais...

Funções:

  1. meta.__
  2. meta.cp
  3. meta.def
  4. meta.defmetametodo
  5. meta.mescle

Variáveis:

  1. meta

meta.pris

Biblioteca para facilitar a manipulação de metatabelas e metamétodos.
* *

Metatabela

*

Metatabela é uma tabela normal Prisma, porém ela fica oculta dentro do objeto (que pode ser uma string, uma tabela, userdata etc). Essa metatabela tem campos chamados metamétodos, responsáveis por mudar o comportamento do objeto em uma operação (que pode ser aritmética, concatenação, tamanho, tipo etc); *

Metamétodos

Metamétodos são funções dentro de metatabelas, com nomes específicos de acordo com as operações e ações. É possível, por exemplo, definir um metamétodo em Prisma para somar duas tabelas, ou para mudar o nome do seu tipo.

Veja o exemplo abaixo:
📋
 ex1.prisma
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
   
     local mt = {}; //metatabela;
     mt.__tipo = funcao()  //metamétodo acionado com a função tipo();
         retorne 'retangulo';
     fim
     
     mt.__convstring = funcao(t)
         local s = 'retangulo:{comprimento=' .. t.comprimento .. ', largura=' .. t.largura .. '}';
         retorne s;
     fim
     local ret = {comprimento=10, largura=20};
     defmetatabela(ret, mt); //definindo a tabela mt como metatabela de ret;
     
     //só testar:
     
     imprima(tipo(ret) ); //--> retangulo
     imprima(ret); // --> retangulo:{comprimento=10, largura=20}
       
   
Esta lib serve para fazer o que foi feito acima, mas de um jeito mais simples. Veja:
📋
 ex2.prisma
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
     local meta = inclua'meta';
     
     local ret = {comprimento=10, largura=20};
     meta.__('tipo', ret, funcao() retorne 'retangulo'; fim);
     meta.__('convstring', ret, 
     funcao(t) 
         local s = 'retangulo:{comprimento=' .. t.comprimento .. ', largura=' .. t.largura .. '}';
         retorne s;
     fim);
     //agora só testar
     imprima(tipo(ret)); //--> retangulo
     imprima(ret);// --> retangulo:{comprimento=10, largura=20}
   
Note que foram usados dois underlines(sublinhado) como método de meta: meta.__

Funções:

Voltar ao início

funcao meta.cp(a,b)

Função para copiar uma metatabela de uma tabela para outra tabela.

Parâmetros:

a(tabela) é a tabela destino, a qual irá receber a metatabela copiada da tabela 'b'
b(tabela) é a tabela alvo com a metatabela a ser copiada.
OBS.: caso não exista uma metatabela em 'b' então nada é feito.

Retornos:

mt(tabela) o retorno é a metatabela copiada de 'b' para 'a' ou nulo caso não exista.
Voltar ao início

funcao meta.def(tab, mt)

Funcao para definir uma tabela 'mt' como metatabela da tabela 'tab'.

- funcao meta.def(tab, mt)

Parâmetros:

tab(tabela) é a tabela que receberá a metatabela 'mt';
mt(tabela) é uma tabela com metamétodos definidos.

Retornos:

tab(tabela) o retorno é a própria tabela passada como parâmetro.

Veja o exemplo abaixo:
📋
 
  1
  2
  3
  4
  5
  6
  7
  8

    local meta = inclua'meta';
    local mt = { __add = funcao(a,b) a.val = a.val + b; retorne a.val; fim }; //meta tabela com metamétodo + definido
    local tab = {val = 0;};
    tab = meta.def(tab, mt);
    imprima(tab+10); //--> 10
    imprima(tab+1); //---> 11    

****************************
Voltar ao início

funcao meta.mescle(tab, mt)

Funcao para mesclar uma tabela'mt' como metatabela da tabela 'tab'.

Se houver uma metatabela em tab ela não será apagada, apenas os metamétodos presentes em mt substituirão os já existentes na tabela original, senão serão apenas acrescentados.

Parâmetros:

tab(tabela) é a tabela que receberá a metatabela 'mt' para ser mesclada na metatabela já existente
mt(tabela) é uma tabela com metamétodos definidos

Retornos:

tab(tabela) o retorno é a própria tabela passada como parâmetro.

Veja um exemplo:
📋
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15

local tab = {n=0};
local mt = {__add=funcao(a, n) a.n = a.n + n; retorne a.n; fim};
local mt2 = {__sub = funcao(a, n) a.n = a.n - n; retorne a.n; fim};
local mt3 = {__mul = funcao(a,n) a.n = a.n * n; retorne a.n; fim};
local mt4 = {__div = funcao(a,n) a.n = a.n / n; retorne a.n; fim};
tab = meta.def(tab, mt);
meta.mescle(tab, mt2);
meta.mescle(tab, mt3);
meta.mescle(tab, mt4);
imprima(tab + 10);
imprima(tab - 1);
imprima(tab * 3);
imprima(tab / 9);

Voltar ao início

funcao meta.defmetametodo(meta, tab, func)

Função para facilitar a definição de metamétodos em Prisma, fazendo a sobrecarga de operadores.

funcao defmetametodo( meta, tab, func)

Parâmetros:

meta(string) contendo o metamétodo ou operador a ser atribuído à tabela.
exemplo: '+' (soma), '-' (sub), '*' (mul), '&' (and bitwise) etc.
tab(tabela) é a tabela a ser atribuído ou modificado o metamétodo.
Obs.: o 2nd parâmetro deve ser sempre uma tabela em Prisma
func é a função a ser executada na operação do metamétodo. Por exemplo:
ao atribuir '+' em tab com a função func(), func() será chamada se fizermos a operação de adição: a+b

Retornos:

tab(tabela) o retorno é a própria tabela com os metamétodos já modificados.
Voltar ao início

funcao meta.__(meta, tab, func) fim;

Esta função meta.__() é um açúcar sintático, um atalho para a função meta.defmetametodo() ficando mais curta assim.

veja:
📋
 
  1
      meta.defmetametodo() == meta.__()
Aqui temos um exemplo de sobrecarga dos operadores de + e de -
📋
 
  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
local meta = inclua'meta';
local myint = Classe{val = 0};
funcao myint:construtor(val) //funcao construtora:
    meta.__('+', este, 
        funcao (a,b)
            local c = {val=0};
            meta.cp(c,a);
            c.val = a.val + b.val;
            retorne c;
    fim)

    meta.__('-', este, 
        funcao (a,b)
            local c = {val=0};
            meta.cp(c,a);
            c.val = a.val - b.val;
            retorne c;
    fim)
    
    meta.__('s', este, 
        funcao(a)
            retorne convstring(a.val);        
    fim)
    este.val = val;
fim



local a = myint(1);
local b = myint(2);
imprima(a + b);
imprima(a - b);

meta.__('tipo', b, funcao() retorne 'myint'; fim);

imprima(tipo(b));

Variáveis

Voltar ao início

local meta = {};

meta é a tabela com os métodos para esta biblioteca prisma.

Obs.: ela é local portanto ao usar o inclua'' deve-se atribuir o valor de retorno: ex.: local meta = inclua'meta';