Macroexecução em AdvPL – Parte 01

Introdução

Em um tópico anterior, foi abordado um recurso do AdvPL conhecido por CodeBlock, ou bloco de código (https://siga0984.wordpress.com/2014/12/12/codeblocks-em-advpl-parte-01/). No tópico de hoje, vamos abordar outro recurso muito interessante da linguagem, orientado a execução de expressões dinâmicas, compiladas em memória e executadas. A leitura do post anterior sobre Blocos de Código é interessante e recomendável, pois podemos usar a macroexecução de uma forma bem similar aos blocos de código, porém com características diferenciadas.

Macro-execução ( ou macro-substituição )

Na TDN, existe uma documentação superficial sobre o operador de macroexecução “&” da linguagem AdvPL, disponível em http://tdn.totvs.com/pages/viewpage.action?pageId=6063087. Vamos extender um pouco este conceito e explicar isso com um pouco mais de profundidade.

O operador de macroexecução permite executar uma expressão AdvPL contida dentro de uma variável do tipo “C” Caractere, em qualquer ponto do código. Esta expressão AdvPL pode ser uma constante, uma atribuição, uma chamada de função básica da linguagem, e pode conter mais de uma expressão, separada por vírgula.

Exemplo 01 – Chamada de função

User Function Macro01()
Local cMacro, cResult
cMacro := "time()" 
cResult := &(cMacro)
MsgInfo("Hora atual no servidor = "+cResult)
Return

O programa acima armazena dentro da variável cMacro a string “Time()”, para chamar a função básica do AdvPL Time(), que retorna a hora atual do sistema operacional da máquina onde o TOTVS Application Server está sendo executado, armazenando o resultado da execução da função na variável cResult, e mostrando seu conteúdo em uma caixa de diálogo na interface.

Exemplo 02 – Chamada com parâmetros constantes

Podemos chamar uma função via macro-execução informando parâmetros de três formas diferentes. No primeiro exemplo, vamos chamar a função Str(), informando dois parâmetros constantes:

User Function Macro02()
Local cMacro, cResult
cMacro := "str(10,10,2)" 
cResult := &(cMacro)
MsgInfo("Resultado = "+cResult)
Return

O resultado do programa acima será a exibição em tela a string com o tamanho de 10 bytes, com espaços a esquerda, e o valor 10 com duas casas decimais (” 10.00″) .

Exemplo 03 – Mais de uma expressão

Podemos separar as expressões com vírgula. Neste caso, todas as expressões serão executadas da esquerda para a direita, e o retorno da macroexecução será a última expressão da macro.

User Function Macro03()
Local cMacro, cResult
cMacro := "x := time(),conout(x),x" 
cResult := &(cMacro)
MsgInfo("Hora atual no servidor = "+cResult)
Return

Reparem que a expressão fez primeiro uma atribuição em linha criando a variavel X dentro da macro, depois executou a função conout() informando X como parâmetro, e por fim retornou X.

Exemplo 04 – Passagem de variáveis como parâmetro

Sim, é possível passar variáveis como parâmetro para chamadas em macro-execução, porém existe uma restrição: Apenas variáveis PRIVATE ou STATIC são visíveis dentro da expressão de macro-execução. Veja o exemplo abaixo:

User Function Macro04()
Local cMacro, cResult
PRIVATE cMSg := "Olá Mundo"
cMacro := "MsgInfo(cMSg)" 
&(cMacro)
Return

A variável PRIVATE cMsg contém a string “Olá Mundo”, e a variável de macroexecução contém a chamada da função MagInfo() informando a variável cMsg como parâmetro. Na linha seguinte, realizamos a macro-execução da variável cMacro.

Exemplo 05 – Usando variáveis locais

No exemplo anterior, eu comentei que somente variáveis STATIC ou PRIVATE são visíveis dentro de uma macro-execução. Porém, existe uma sintaxe especial, que pode ser usada apenas quando queremos executar uma única função através da macroexecução, onde todos os parâmetros vão ser informados fora da string a ser macroexecutada. Neste exemplo, vamos adaptar o fonte MACRO02():

User Function Macro05()
Local cMacro, cResult
Local nNumero := 10 , nTamanho := 10 , nDec := 2
cMacro := "str" 
cResult := &cMacro.(nNumero,nTamanho,nDec)
MsgInfo("Resultado = "+cResult)
Return

Colocamos em cMacro apenas o nome da função a ser executada, e na chamada desta função, usamos o operador de macroexecução sem os parênteses para cercar a macroexecução, seguido de um “.()”, onde dentro dos parênteses colocamos constantes ou variáveis, inclusive locais, para serem informadas como parâmetro para a função.

Observação: Caso exista somente um parâmetro a ser informado para a função usando esta sintaxe, o compilador do AdvPL não entende corretamente a intenção de chamada, e considera a função especificada em cMAcro como sendo uma variável, causando erro de execução. Neste caso, é necessário informar um segundo parâmetro na chamada, mesmo que seja NIL, para que o compilador entenda que a intenção é fazer a chamada de uma função com parâmetros via macro. Vejamos o exemplo abaixo:

User Function Macro06()
Local cMacro
cMacro := "MsgInfo" 
&cMacro.(time(),NIL)
Return

Desempenho

Qualquer chamada feita diretamente na linguagem AdvPL em tempo de compilação vai ser mais rápida do que a macroexecução. Deste modo, somente usamos a macroexecução quando dependemos de um conteúdo dinâmico, normalmente armazenado na base de dados ou fornecido pelo usuário durante a execução do programa. A diferença de tempo será mais significativa (pior) na macro-execução quanto maior e mais complexa for a expressão a ser executada. Por isso, quando usamos múltiplas expressões ou muitas operações dentro de uma macroexecução, devemos tomar cuidado de não fazer uma string muito grande.

Outro ponto a ser considerado é a execução em loop de processamento. Como já vimos anteriormente, diferenças de centésimos de segundo podem transformar-se em segundos e minutos dependendo de quantas iterações são realizadas em uma parte do código. Este post termina aqui, mas ele serve de base para a próxima abordagem, onde vamos ver as possibilidades de uso para chamadas dinâmicas usando macroexecução junto com Codeblocks (ou blocos de código no AdvPL)

Até o próximo post, pessoal 😀

Anúncios

Um comentário sobre “Macroexecução em AdvPL – Parte 01

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s