4D v16.3

Utilización de directivas de compilación

Inicio

 
4D v16.3
Utilización de directivas de compilación

Utilización de directivas de compilación  


 

4D tiene tres categorías de variables:

  • Variables locales,
  • Variables proceso,
  • Variables interproceso.

Para mayor información sobre este punto, consulte la sección Variables. Las variables proceso e interproceso son estructuralmente de la misma naturaleza del compilador.

Como el compilador no puede determinar el proceso en el cual la variable será utilizada, las variables proceso deben utilizarse con más cuidado que las variables interproceso. Todas las variables proceso se duplican sistemáticamente cuando comienza un nuevo proceso. Una variable proceso puede tener un valor diferente en cada proceso, pero tiene el mismo tipo en toda la base.

Todas las variables tienen un tipo. Como se describe en la sección Tipos de datos, hay varios tipos de variables:

Booleano
Alfanumérico (o cadena fija)
Fecha
Entero
Entero largo
Gráfico
Hora
Imagen
Número (o Real)
Puntero
Texto
BLOB
Objeto

Para las variables de tipo Array, dispone de los siguientes tipos:

Array Booleano
Array Alfa
Array Fecha
Array Entero
Array Entero largo
Array Imagen
Array Real
Array Hora
Array Objeto
Array Puntero
Array BLOB
Array Texto

Notas:
- El tipo "objeto" está disponible a partir de 4D v14.
- Los tipos anteriores Alfa (cadena de longitud fija) y Entero no se utilizan más para las variables. En el código existente, se redirigen automáticamente a los tipos Texto y Entero largo.

En modo interpretado, una variable puede tener más de un tipo de datos. Esto es posible porque el código es interpretado en lugar de compilado. 4D interpreta cada instrucción por separado y comprende su contexto. Cuando trabaja en modo compilado, la situación es diferente. Mientras la interpretación se realiza línea por línea, el proceso de compilación mira a una base en su globalidad.

La manera de operar el compilador es la siguiente:

  • El compilador analiza sistemáticamente los objetos en la base. Los objetos son los métodos base, proyecto, formulario, trigger y objeto.
  • El compilador escanea los objetos para determinar el tipo de dato de cada variable utilizada en la base y genera la tabla de variables y métodos (la tabla símbolo).
  • Una vez establecidos los tipos de datos de todas las variables, el compilador traduce (compila) la base. Sin embargo, no puede compilar la base a menos que pueda determinar el tipo de dato de cada variable.

Si el compilador encuentra el mismo nombre de variable en dos tipos diferentes de datos, no tiene ninguna razón para favorecer a uno de ellos. En otras palabras, para clasificar un objeto y darle una dirección de memoria, el compilador debe saber la identidad precisa del objeto (es decir, su nombre y su tipo). El tipo le permite al compilador determinar el tamaño. Para cada base compilada, el compilador crea un mapa que lista, para cada variable, su nombre (o identificador), su ubicación (o dirección de memoria), y el espacio que ocupa (indicado por su tipo). Este mapa se llama la tabla de símbolos. Una opción en las preferencias le permite generar o no esta tabla en forma de archivo durante la compilación.

Este mapa también se utiliza para la generación automática de métodos compilador.

Si quiere que el compilador verifique los tipos de sus variables o que declare las variables él mismo, es fácil colocar una directiva de compilación para este propósito. Puede elegir entre dos posibilidades diferentes, dependiendo de sus métodos de trabajo:

  • Utilice la directiva en el método en el cual aparece la variable por primera vez, dependiendo si es una variable local, proceso o interproceso. Asegúrese de utilizar la directiva la primera vez que utilice la variable, en el primer método a ejecutar. Recuerde que durante la compilación, el compilador toma los métodos en el orden de su creación en 4D, y no en el orden en el cual aparecen en el Explorador.
  • O si usted es sistemático, agrupe todos las variables proceso e interproceso con las diferentes directivas de compilación en el Método base On Startup o en un método llamado por el Método de base de datpos On Startup.
    Para las variables locales, agrupe las directivas al comienzo del método en el cual aparecen.

Cuando las variables se digitan por medio de una directiva de compilación, reciben un valor por defecto, que se conserva durante la sesión, siempre y cuando no se hayan asignado.

El valor por defecto depende del tipo y la categoría variable, del contexto de ejecución (interpretado o compilado), así como, para el modo compilado, la6s opciones de compilación definidas en la Página Compilador de las Propiedades de la base:

  • Las variables de proceso e interprocesos se definen siempre "en cero" (lo que significa, según el caso, "0", una cadena vacía, un Blob vacío, un puntero Nil, una fecha vacía (00-00-00), etc.)
  • Las variables locales se definen:
    • en modo interpretado: en cero
    • en modo compilado, dependiendo de la opción Inicializar las variables locales de las Propiedades de la base:
      • en cero cuando "en cero" esté seleccionado,
      • en un valor aleatorio definido cuando "en un valor aleatorio" se elige (0x72677267 para los números y horas, siempre es True para booleanos, lo mismo que "en cero" para los demás),
      • en un valor aleatorio (para los números) cuando "no" esté seleccionado.
La siguiente tabla ilustra estos valores por defecto:
TipoInterprocesoProcesoLocal interpretadoLocal compilado "en cero"Local compilado "aleatorio"Local compilado "no"
BooleenoFalseFalseFalseFalseTrueTrue (varía)
Fecha00-00-0000-00-0000-00-0000-00-0000-00-0000-00-00
Entero largo00001919382119909540880 (varía)
Gráfico00001919382119775946656 (varía)
Hora00:00:0000:00:0000:00:0000:00:00533161:41:59249345:34:24 (varía)
Imagenpicture size=0picture size=0picture size=0picture size=0picture size=0picture size=0
Real00001.250753659382e+2431.972748538022e-217 (varía)
PunteroNil=trueNil=trueNil=trueNil=trueNil=trueNil=true
Text""""""""""""
BlobBlob size=0Blob size=0Blob size=0Blob size=0Blob size=0Blob size=0
Objetoindefinidoindefinidoindefinidoindefinidoindefinidoindefinido

Las directivas de compilación son útiles en dos casos:
• cuando el compilador no puede determinar el tipo de dato de una variable por su contexto,
• cuando usted no quiere que el compilador determine el tipo de la variable por su uso.
Adicionalmente, utilizar directivas de compilación le permite reducir el tiempo de compilación.

Algunas veces el compilador no puede determinar el tipo de dato de una variable y genera un mensaje de error.
Hay tres causas principales que pueden evitar que el compilador determine el tipo de dato: tipos de datos múltiples, ambigüedad sobre una deducción forzada y la imposibilidad de determinar un tipo.

  • Tipos de datos múltiples
    Si una variable tiene diferentes tipos en diferentes instrucciones en la base, el compilador genera un error que es fácil de solucionar.
    El compilador selecciona la primera variable que encuentra y le asigna su tipo de dato a la siguiente ocurrencia de la variable con el mismo nombre pero un tipo diferente.

    Este es un ejemplo sencillo:

en un método A,

 Variable:=True

en un método B,

 Variable:="La luna es verde"

Si el método A se compila antes que el método B, el compilador considera que Variable:="La luna es verde" es un cambio de tipo de una variable encontrada anteriormente. El compilador le notifica que ha ocurrido un cambio de tipo. Esto genera un error que debe corregir. En la mayoría de los casos, el problema puede solucionarse renombrando la segunda ocurrencia de la variable.

  • Ambigüedad sobre una deducción forzada
    Algunas veces, por una secuencia, el compilador puede deducir que un tipo de objeto no es el apropiado. En este caso, debe explícitamente darle tipo a la variable con una directiva de compilación.

    Este es un ejemplo utilizando los valores por defecto para un objeto activo:
    En un formulario, puede asignar valores por defecto para los siguientes objetos: combo boxes, pestañas, listas y menús desplegables y áreas de desplazamiento utilizando el botón de edición de Valores por defecto (en el tema Fuente de datos de la Lista de propiedades) (para mayor información, consulte el Manual de Diseño). Los valores por defecto se cargan automáticamente en un Array cuyo nombre es el mismo del objeto.
    Si el objeto no se utiliza en un método, el compilador puede deducir el tipo, sin ambigüedad, como un array de texto.
    Sin embargo, si se debe efectuar una inicialización, la secuencia podría ser:
 Case of
    :(Form event=On Load)
       MiPopUp:=2
       ...
 End case

En este caso, aparece la ambigüedad, durante el análisis de los métodos, el compilador deducirá un tipo de dato Real para el objeto MiPopUp. En este caso, es necesario declarar explícitamente el Array en el método de formulario o en un método compilador:

 Case of
    :(Form event=On Load)
       ARRAY TEXT(MiPopUp;2)
       MiPopUp:=2
       ...
 End case


• Imposibilidad para determinar un tipo
Este caso puede surgir cuando una variable se utiliza sin haber sido declarada, en un contexto que no ofrece información sobre su tipo. En este caso, sólo una directiva de compilación puede guiar el compilador.
Este fenómeno ocurre principalmente en cuatro contextos:
- cuando utiliza punteros,
- cuando utiliza un comando con más de una sintaxis,
- cuando utiliza un comando con parámetros opcionales de diferentes tipos de datos,
- cuando utiliza un método 4D llamado vía un URL.

- Punteros
No se puede esperar que un puntero devuelva un tipo diferente al propio.
Considere la siguiente secuencia:

 Var1:=5.2(1)
 Puntero:=->Var1(2)
 Var2:=Puntero->(3)

Aunque la línea (2) defina el tipo de variable apuntada por el puntero, el tipo de Var2 no se determina. En el momento de la compilación, el compilador puede reconocer un puntero, pero no tiene ningún medio de saber a que tipo de variable apunta. Por lo tanto no puede deducir el tipo de Var2. Se necesita una directiva de compilación, por ejemplo C_REAL(Var2).

- Comandos de sintaxis múltiple
Cuando utiliza una variable asociada con la función Year of, la variable sólo puede ser de tipo Fecha, considerando la naturaleza de esta función. Sin embargo, las cosas no siempre son simples. Este es un ejemplo:
El comando GET FIELD PROPERTIES acepta dos sintaxis:
GET FIELD PROPERTIES(tablaNo;campoNo;Tipo;longitud;indice)
GET FIELD PROPERTIES(campoPuntero;Tipo;longitud;indice)

Cuando utiliza un comando de sintaxis múltiple, el compilador no puede adivinar la sintaxis y los comandos que usted escogío. Debe utilizar directivas de compilación para darle un tipo a las variables que se pasan al comando, si no tienen un tipo de acuerdo a su uso en la base.

- Comandos con parámetros opcionales de diferentes tipos
Cuando utiliza un comando que contiene varios parámetros opcionales de diferentes tipos, el compilador no puede determinar que parámetros opcionales han sido utilizados. Este es un ejemplo:
El comando GET LIST ITEM acepta dos parámetros opcionales; el primero es de tipo Entero largo y el segundo de tipo Booleano.
El comando puede ser utilizado:
GET LIST ITEM(lista;posición;itemRef;texto;sublista;expandido)
o como:
GET LIST ITEM(lista;posición;itemRef;texto;expandido)
Debe utilizar directivas de compilación para dar tipo a los parámetros opcionales pasados al comando, si no tienen tipos de acuerdo a su uso en la base.

- Métodos llamados vía URLs
Si escribe métodos 4D que deben llamarse vía un URL y si no utiliza $1 en el método, debe declarar explícitamente la variable texto $1 con la siguiente secuencia:
C_TEXT($1)
De hecho, el compilador no puede determinar que el método 4D se llamará vía un URL.

Si todas las variables utilizadas en la base se declaran explícitamente, no es necesario que el compilador revise los tipos. En este caso, puede fijar las opciones de manera que el compilador sólo ejecute la fase de traducción del método. Esto ahorra por lo menos el 50% del tiempo de compilación.

Usted puede acelerar sus métodos utilizando directivas de compilación. Para mayor información al respecto, consulte la sección Consejos de optimización . Para dar un ejemplo simple, imagine que necesita incrementar un contador utilizando una variable local. Si no declara la variable, el compilador asume que es de tipo Real. Si la declara como de tipo Entero largo, la ejecución de la base compilada será más eficiente. En un PC, por ejemplo, un Real ocupa 8 bytes en memoria, mientras que el tipo Entero largo, sólo utiliza 4 bytes. Incrementar un contador de 8 bytes obviamente toma más tiempo que aumentar un contador de 4 bytes.

Las directivas de compilación se pueden manejar de dos formas diferentes, dependiendo de si quiere que el compilador verifique o no los tipos de sus variables.

El compilador debe respetar el criterio de identificación de las variables.
Hay dos posibilidades:

  • Si la variable no tiene tipo, el compilador se ocupará de eso automáticamente. Siempre que sea posible, siempre y cuando no haya ambigüedad, el compilador determina un tipo de variable dependiendo de su uso. Por ejemplo, si escribe:
 V1:=True

el compilador determina que la variable V1 es de tipo booleano.

De la misma forma, si escribe:

 V2:="Esta es una frase de ejemplo"

el compilador determina que V2 es una variable de tipo texto.

El compilador también es capaz de establecer el tipo de dato de una variable en casos menos fáciles:

 V3:=V1 `V3 es del mismo tipo que V1
 V4:=2*V2 `V4 es del mismo tipo que V2

El compilador también determina el tipo de datos de sus variables de acuerdo a los llamados a los comandos 4D y a sus métodos. Por ejemplo si pasa un parámetro tipo booleano y un parámetro tipo fecha a un método, el compilador asigna el tipo booleano y el tipo fecha a las variables locales $1 y $2 del método llamado.

Cuando el compilador determina el tipo de dato por deducción, a menos de que se indique de otra forma en las Propiedades de la base, el compilador asigna el tipo de dato más amplio posible. Por ejemplo, si escribe:

 Número:=4

el compilador asigna el tipo de dato Real, aunque 4 sea un entero. En otras palabras, el compilador no descarta la posibilidad de que, bajo otras circunstancias, el valor de la variable pueda ser 4.5.

Si es conveniente darle a una variable un tipo Entero, Entero largo, o Alfa, puede hacer utilizando una directiva de compilación. Es una ventaja hacerlo, porque estos tipos de datos ocupan menos memoría y es mucho más rápido efectuar operaciones en ellos.

Si ya ha asignado un tipo a sus variables y está seguro de que su tipo coherente y completo, puede pedirle explícitamente al compilador no hacer nuevamente este trabajo, utilizando las Preferencias de compilación. En caso de que los tipos que asignó no estén completos, al momento de la compilación, el compilador devolverá errores solicitándole hacer las modificaciones necesarias.

  • Los comandos de las directivas de compilación le permiten declarar explícitamente las variables utilizadas en sus base.

Se utilizan de la manera siguiente:

 C_BOOLEAN(Var)

A través de tales directivas, usted le dice al compilador que cree una variable Var que será de tipo Booleano.
Cuando una aplicación incluye directivas de compilación, el compilador las detecta y evita hacer conjeturas.

Una directiva de compilación tiene prioridad sobre una deducción hecha de una asignación o uso.

Las variables declaradas por la directiva de compilación C_INTEGER en realidad son iguales a las declaradas por la directiva C_LONGINT. De hecho son enteros largos entre –2147483648 y +2147483647.

Si no quiere que el compilador revise los tipos, debe darle un código para identificar las directivas de compilación.
La convención es la siguiente:
Las directivas de compilación de las variables proceso e interproceso y los parámetros deben ubicarse en uno o más métodos, cuyos nombres comiencen con la palabra clave Compiler.
Por defecto, el compilador le permite generar automáticamente cinco tipos de métodos Compiler, los cuales agrupan la directivas para las variables, arrays y los parámetros de los métodos (para mayor información sobre este punto, consulte el Manual de Diseño).

Nota: la sintaxis para la declaración de estos parámetros es:
Directiva (nombreMétodo;Parámetro). Esta sintaxis no es ejecutable en modo interpretado.

Parámetros particulares
• Los parámetros recibidos por los métodos base

Si estos parámetros no han sido declarados explícitamente, son declarados por el compilador. Sin embargo, si los declara, la declaración se debe hacer dentro de los métodos de base de datos.
La declaración de estos parámetros no puede hacerse en un método compilador.
Ejemplo: Método de base de datos On Web Connection recibe seis parámetros, $1 a $6, de tipo texto. Al comienzo del método, debe escribir: C_TEXT($1;$2;$3;$4;$5;$6)

• Triggers

El parámetro $0 (Entero largo), es el resultado de un trigger, es declarado por el compilador el parámetro no ha sido declarado explícitamente. Sin embargo, si quiere declararlo, debe hacerlo en el trigger.
La declaración de este parámetro no puede hacerse en un método compilador.

• Los objetos aceptan el evento de formulario “On Drag Over”

El parámetro $0 (Entero largo), es el resultado de un evento de formulario “On Drag Over”, es declarado por el compilador si el parámetro no ha sido declarado explícitamente. Sin embargo, si quiere declararlo, debe hacerlo en el método de objeto.
La declaración de este parámetro no puede escribirse en un método compilador.

Nota: el compilador no inicializa el parámetro $0. De manera que tan pronto utilice el evento de formulario On Drag Over, debe inicializar $0. Por ejemplo:

 C_LONGINT($0)
 If(Form event=On Drag Over)
    $0:=0
    ...
    If($DataType=Is picture)
       $0:=-1
    End if
    ...
 End if

Las directivas de compilación eliminan toda ambigüedad sobre los tipos de datos. Aunque es necesario cierto rigor, esto no significa que el compilador sea intolerante con cualquier inconsistencia.
Por ejemplo, si asigna un valor real a una variable declarada como de tipo Entero, el compilador no considera que haya un conflicto de tipo y asigna los valores correspondientes de acuerdo a sus directivas. De manera que si escribe:

 C_LONGINT(vInteger)
 vInteger:=2.6


El compilador no verá esto como un conflicto de datos que impida la compilación; el compilador simplemente redondeará al valor entero más cercano (3 en lugar de 2.6).



Ver también 

Consejos de optimización
Detalles de sintaxis
Guía de declaración
Mensajes de error

 
PROPIEDADES 

Producto: 4D
Tema: Compilador

 
HISTORIA 

 
ARTICLE USAGE

Manual de lenguaje 4D ( 4D v16)
Manual de lenguaje 4D ( 4D v16.1)
Manual de lenguaje 4D ( 4D v16.2)
Manual de lenguaje 4D ( 4D v16.3)