Para mais informações sobre este ponto, consulte a seção Variáveis. Processos e variáveis interprocesso são estruturalmente o mesmo para o compilador.
Desde que o compilador não pode determinar o processo no qual a variável será utilizada, variáveis do processo devem ser usadas com mais cuidado do que variáveis de processos. Todas as variáveis do processo são sistematicamente repetidas quando um novo processo começa. A variável de processo pode ter um valor diferente em cada processo, mas tem o mesmo tipo para todo o banco de dados.
Todas as variáveis têm um tipo. Conforme descrito na seção Tipos de dados, existem 13 diferentes tipos de variáveis:
Booleano
Alfanumérico (ou cadeia fixa)
Data
Inteiro
Inteiro longo
Gráfico
Hora
Imagem
Número (o Real)
Ponteiro
Texto
BLOB
Objeto
Para as variáveis de tipo Array, dispõem dos seguintes tipos:
Array Booleano
Array Alfa
Array Data
Array Inteiro
Array Inteiro longo
Array Imagem
Array Real
Array Hora
Array Objeto
Array Ponteiro
Array BLOB
Array Texto
Notas: - O tipo "objeto" está disponível a partir de 4D v14. - Os tipos anteriores Alfa (string de tamanho fixo) e Inteiro não se usam mais para as variáveis. No código existente, säo redigidas automaticamente aos tipo Textoe Inteiro Longo.
Em modo interpretado, uma variável pode ter mais de um tipo de dados. Isso é possível porque o código é interpretado e não compilado. 4D interpreta cada instrução separadamente, e compreende o seu contexto. Quando você trabalha em um ambiente de compilação, a situação é diferente. Embora a interpretação é realizada linha por linha, o processo de compilação olha para um banco de dados na sua totalidade.
A abordagem do compilador é a seguinte:
O compilador analisa sistematicamente os objetos no banco de dados. Os objetos são os métodos de banco de dados, projeto, formulário, trigger e métodos de objeto.
O compilador verifica os objetos para determinar o tipo de dados de cada variável no banco de dados, e gera a tabela de variáveis e métodos (tabela de símbolos).
Uma vez estabelecidos os tipos de dados de todas as variáveis, o compilador converte (compila) o banco de dados. No entanto, ele não pode compilar o banco de dados, a menos que possa determinar o tipo de dados para cada uma das variáveis.
Se o compilador vem através do mesmo nome de variável e dois tipos de dados diferentes, não há nenhuma razão para favorecer qualquer um em particular. Em outras palavras, para um tipo de objeto e dar-lhe um endereço de memória, o compilador deve saber a identidade exata daquele objeto (ou seja, o seu nome e tipo de dados). O compilador determina o tamanho do tipo de dados. Para cada banco de dados compilado, o compilador cria um mapa que relaciona, para cada variável, o seu nome (ou identificador), a sua localização (ou endereço de memória), e o espaço que ocupa (indicado pelo seu tipo de dados). Este mapa é chamado de tabela de símbolos. Uma opção em Preferências permite que você escolha se deseja gerar esta tabela na forma de um arquivo durante a compilação.
Este mapa é também utilizado para a geração automática dos métodos de compilação.
Se você quiser que o compilador verifique a digitação de suas variáveis ou digitá-las em si, é fácil colocar uma diretiva de compilador para essa finalidade. Você pode escolher entre duas possibilidades diferentes, dependendo do seu método de trabalho:
Ou use a diretiva no método em que a variável aparece pela primeira vez, dependendo se é local, processo ou variável interprocessos. Certifique-se de usar a diretiva da primeira vez que você usar a variável, no primeiro método a ser executado. Tenha em mente que durante a compilação, o compilador tem os métodos na ordem de sua criação, em 4D, e não na ordem em que são exibidos no Explorer.
Ou, se for sistemático em sua abordagem, agrupe todas as variáveis de processo e interprocesso com as diferentes diretivas de compilador no método Método banco de dados On Startup ou em um método chamado porMétodo banco de dados On Startup. Para as variáveis locais, agrupe as diretivas no início do método em que elas aparecem.
Quando as variáveis são digitadas por meio de uma diretiva de compilador, recebem um valor padrão, que elas vão manter durante a sessão desde que não tenham sido atribuídas.
O valor padrão depende do tipo de variável e categoria, o seu contexto de execução (interpretada ou compilada), bem como, para o modo compilado, as opções de compilação definidas em Página Compilador das configurações de banco de dados:
As variáveis do processo e entre processos são sempre definidas como "zero" (o que significa que, dependendo do caso, "0", uma string vazia, uma Blob vazia, um ponteiro Nil, uma data em branco (00-00-00), etc)
As variáveis locais são definidas:
em modo interpretado: a zero
em modo compilado, dependendo da opção Inicializar variáveis locais das configurações de banco de dados:
a zero quando "a zero" é escolhido,,
para um valor aleatório definido quando "a um valor aleatório" é escolhido (0x72677267 para números e horas, sempre TRUE para Booleans, o mesmo que "a zero" para os outros),
para um valor aleatório (para números) quando "não" for escolhido.
Diretivas do compilador são úteis em dois casos: • O compilador é incapaz de determinar o tipo de dados de uma variável de seu contexto, • Você não quer que o compilador determine o tipo de uma variável para sua utilização. Além disso, usar diretivas de compilador permite reduzir o tempo de compilação.
Às vezes o compilador não pode determinar o tipo de dados de uma variável. Sempre que não pode fazer uma determinação, o compilador gera uma mensagem de erro apropriada. Existem três principais causas que impedem o compilador de determinar o tipo de dados: vários tipos de dados, a ambigüidade em uma dedução forçada e a impossibilidade de determinar um tipo de dados.
Vários tipos de dados Se uma variável tem tido o tipo retribuído de declarações diferentes no banco de dados, o compilador gera um erro que é fácil de corrigir. O compilador seleciona a primeira variável que encontra e arbitrariamente atribui a seu tipo de dados para a próxima ocorrência da variável com o mesmo nome, mas um tipo de dados diferente.
Aqui está um exemplo simples:
no método A,
Variable:=True
no método B,
Variable:="A lua é verde"
Se o método A é compilado antes o método B, o compilador considera a declaração Variável: = "A lua é verde" como uma mudança de tipo de dados em uma variável anteriormente encontrada. O compilador avisa que uma redefinição de tipo ocorreu. Ele gera um erro para você corrigir. Na maioria dos casos, o problema pode ser corrigido por renomear a segunda ocorrência da variável.
Ambigüidade em uma dedução forçada Às vezes, devido a uma seqüência, o compilador pode deduzir que um tipo de objeto não é do tipo adequado para ele. Neste caso, você deve explicitamente digitar o tipo da variável com uma diretiva do compilador.
Aqui está um exemplo usando os valores padrão para um objeto ativo: Em um formulário, você pode atribuir valores padrão para os seguintes objetos: caixas de combinação, menus pop-up, controles de guia para listas , menus / listas drop-down e áreas roláveis usando o botão Editar para a Lista de Valores (sob o tema Controle de Entrada da lista de propriedades) (para mais informações, consulte o manual de referência Desenho 4D). Os valores padrão são automaticamente carregados em um array cujo nome é o mesmo que o nome do objeto. Se o objeto não é usado em um método, o compilador pode inferir o tipo, sem ambiguidade, como um array de texto. No entanto, se uma inicialização de exibição deve ser realizada, a seqüência poderia ser:
Case of
:(Form event=On Load) MieuPopUp:=2
... End case
Neste caso, a ambigüidade aparece - quando os métodos de análise, o compilador irá inferir um tipo de dados reais para o objeto MyPopUp. Neste caso, é necessário declarar explicitamente o array no método de formulário ou em um método de compilador:
Case of
:(Form event=On Load) ARRAY TEXT(MiPopUp;2) MeuPopUp:=2
... End case
• Incapacidade de determinar um tipo de dados Este caso pode surgir quando uma variável é usada sem ter sido declarada, dentro de um contexto que não fornecem informações sobre o tipo de dados. Aqui, só uma diretiva do compilador pode guiar o compilador. Este fenômeno ocorre principalmente nos quatro contextos: - quando os ponteiros são usados, - quando você usa um comando com mais de uma sintaxe, - quando você usar um comando com parâmetros opcionais ou diferentes tipos de dados, - quando você usa um método 4D chamado através de uma URL.
- Ponteiros Um ponteiro não pode esperar para retornar um tipo de dados que não sejam seus. Considere a seguinte seqüência:
Var1:=5.2(1)
Ponteiro
:=->Var1(2) Var2:=Ponteiro->(3)
Embora (2) define o tipo de variável apontada pelo ponteiro, o tipo de Var2 não está determinada. Durante a compilação, o compilador pode reconhecer um ponteiro, mas não tem como saber que tipo de variável ele está apontando. Portanto, você não pode deduzir o tipo de dados Var2. Uma diretiva de compilador é necessária, por exemplo C_REAL (var2).
- Comandos Multi-sintaxe Quando você usa uma variável associada com a função de Year of, a variável só pode ser do tipo de dados Date, considerando a natureza desta função. No entanto, as coisas nem sempre são tão simples. Aqui está um exemplo: O comando GET FIELD PROPERTIES aceita duas sintaxes: GET FIELD PROPERTIES(tabelaNo;campoNo;Tipo;comprimento;indice) GET FIELD PROPERTIES(campoPonteiro;Tipo;comprimento;indice)
Quando você um comando de multi-sintaxe - o compilador não pode adivinhar qual a sintaxe e os parâmetros que você selecionou. Você deve usar diretivas de compilador de variáveis de tipo passadas para o comando, se não forem digitadas de acordo com a sua utilização em outras partes do banco de dados.
- Comandos com parâmetros opcionais de diferentes tipos de dados Quando você usa um comando que contém vários parâmetros opcionais de dados de diferentes tipos, o compilador não pode determinar quais os parâmetros opcionais foram utilizados. Aqui está um exemplo: O comando GET LIST ITEM aceita dois parâmetros opcionais: o primeiro como um Longint e o outro como um booleano. O comando pode então ser utilizada da seguinte forma: GET LIST ITEM(lista;posicao;itemRef;texto;sub-lista;expandido) ou como: GET LIST ITEM(lista;posicao;itemRef;texto;expandido) Você deve usar diretivas de compilador de variáveis tipo opcionais passados para o comando, se não forem tipadas de acordo com a sua utilização em outras partes do banco de dados.
- Métodos chamados via URLs Se você escrever métodos 4D que precisam ser chamados através de uma URL, e se você não usar $1 no método, você deve declarar explicitamente a variável de texto $1 com a seguinte seqüência: C_TEXT($1) Na verdade, o compilador não pode determinar que o método 4D será chamado através de uma URL.
Se todas as variáveis usadas no banco de dados são explicitamente declaradas, não é necessário para o compilador verificar a tipagem. Neste caso, você pode definir as opções para que o compilador execute somente a fase de tradução do método. Isso economiza pelo menos 50% em tempo de compilação.
Você pode acelerar seus métodos usando diretivas de compilador. Para mais detalhes sobre este assunto, consulte a seção Dicas de otimização. Para dar um exemplo simples, suponha que você precisa incrementar um contador utilizando uma variável local. Se você não declarar a variável, o compilador assume que é um Real. Se você declará-la como um Longint, o banco de dados compilado irá executar com mais eficiência. Em um PC, por exemplo, um Real tem 8 bytes, mas se você digitar o contador como um Longint, utilizará apenas 4 bytes. Incrementar um contador de 8 bytes, obviamente, demora mais do que um incremento de 4 bytes.
Directivas do compilador podem ser tratadas de duas maneiras diferentes, dependendo se você deseja ou não que o compilador atribua um tipo as suas variáveis.
O compilador deve respeitar os critérios de identificação das variáveis. Há duas possibilidades:
Se a variável não está digitada, o compilador pode fazer isso por você automaticamente. Sempre que possível - desde que não haja ambigüidade - o compilador determina um tipo de variável da forma como é utilizado. Por exemplo, se você escrever:
V1:=True
o compilador determina que a variável V1 é de tipo de dados Boolean.
Da mesma forma, se você escrever:
V2:="Esta é uma frase de exemplo"
o compilador determina que V2 é uma variável do tipo texto.
O compilador também é capaz de estabelecer o tipo de dados de uma variável em situações menos simples:
V3:=V1 `V3 é do mesmo tipo que que V1
V4:=2*V2 `V4 é do mesmo tipo que V2
O compilador também determina o tipo de dados das variáveis de acordo com as chamadas para os comandos 4D e de acordo com seus métodos. Por exemplo, se você passar um parâmetro do tipo Booleano e um parâmetro do tipo Data para um método, o compilador atribui o tipo booleano e o tipo data para as variáveis locais $1 e $2 no método chamado.
Quando o compilador determina o tipo de dados por inferência, salvo indicado o contrário nas preferências, nunca atribui os tipos de dados de limitação: Integer, Longint ou String. O tipo padrão atribuído pelo compilador é sempre o mais amplo possível. Por exemplo, se você escrever:
Número:=4
compilador designa o tipo de dados Número Real, apesar de 4 ser apenas um número inteiro. Em outras palavras, o compilador não descarta a possibilidade de que, noutras circunstâncias, o valor da variável poderia ser 4,5.
Se for apropriado para um tipo de variável como Integer, Longint ou String, você pode fazer isso usando uma diretiva de compilador. É a sua vantagem para fazer isso, porque estes tipos de dados ocupam menos memória e executar operações sobre elas é mais rápido.
Se você já digitou suas variáveis e está certo que a sua foi coerente e completo, você pode explicitamente pedir ao compilador para não refazer este trabalho, utilizando as preferências de compilação. No caso de a sua escrita não ter sido completa e exaustiva, no momento da compilação, o compilador retornará um erro solicitando que você faça as modificações necessárias.
Os comandos diretiva de compilador permitem que você declare explicitamente as variáveis utilizadas nos bancos de dados.
Eles são utilizados da seguinte forma:
C_BOOLEAN(Var)
Através de tais diretivas, você informa o compilador para criar uma variável Var que vai ser um booleano. Sempre que um aplicativo inclui diretivas de compilador, o compilador detecta-los e, assim, evita suposições.
Uma diretiva de compilador tem prioridade sobre as deduções feitas a partir de atribuições ou utilização.
Variáveis declaradas com a diretiva de compilador C_INTEGER são realmente as mesmas que as declaradas pela diretiva C_LONGINT. Eles são, na verdade, inteiros longos entre -2147483648 e 2147483647.
Se você não quiser que o compilador verifique a sua tipagem, você deve dar um código para identificar as directivas do compilador. A convenção a seguir é: Diretivas para o compilador e variáveis de processo e interprocesso e os parâmetros devem ser colocados em um ou mais métodos, cujos nomes começam com a palavra chave Compilador. Por padrão, o compilador permite gerar automaticamente cinco tipos de métodos Compilador, que agrupam as diretrizes para as variáveis, matrizes e parâmetros do método (para mais informações sobre este ponto, consulte o manual de Projeto de Referência).
Nota: A sintaxe para declarar esses parâmetros é a seguinte: Diretiva (nomeMétodo;Parametro). Esta sintaxe não é executável em modo interpretado.
Parâmetros particulares • Parâmetros recebidos por métodos de banco de dados
Se esses parâmetros não foram declarados explicitamente, o compilador escolherá o tipo de parâmetro. No entanto, se você declará-los, a declaração deve ser feita dentro dos métodos de banco de dados. Esta declaração de parâmetro não pode ser gravada em um método Compiler. Exemplo: recebe seis parâmetros, $1 a $6, do tipo de dados Texto. No início do método de banco de dados, você deve escrever: C_TEXT ($1, $2, $3, $4, $5, $6)
• Triggers
O parâmetro $0 (Longint), que é o resultado de um trigger, é declarado pelo compilador se o parâmetro não foi explicitamente declarado antes. No entanto, se você quiser declará-lo, você deve fazê-lo no próprio trigger. Esta declaração de parâmetro não pode ser gravada em um método Compiler.
• Objetos que aceitam o evento de formulário "On Drag Over"
O parâmetro $0 (Longint), que é o resultado do evento de formulário "On Drag Over", é digitado pelo compilador se o parâmetro não foi explicitamente declarado. No entanto, se você quiser declará-lo, você deve fazê-lo no próprio método de objeto. Esta declaração de parâmetro não pode ser gravada em um método Compiler.
Nota: O compilador não inicializar o parâmetro $0. Assim, logo que você usar o evento de formulário On Drag Over, você deve inicializar $0. Por exemplo:
C_LONGINT($0) If(Form event=On Drag Over) $0:=0
... If($DataType=Is picture) $0:=-1 End if
... End if
Diretivas do compilador eliminam qualquer ambiguidade sobre os tipos de dados. Apesar de que um certo rigor é necessário, isso não significa necessariamente que o compilador é intolerante de toda e qualquer inconsistência. Por exemplo, se você atribuir um valor real a uma variável declarada como um inteiro, o compilador não considera tanto a atribuição como um tipo de conflito e atribui os valores correspondentes de acordo com suas diretrizes. Então, se você escrever:
C_INTEGER(vInteiro) vInteiro:=2.6
O compilador não considera isso como um conflito do tipo de dados que impedem a compilação, ao contrário, o compilador simplesmente arredonda para o valor inteiro mais próximo (3 em vez de 2,6).