Files
harbour-core/harbour/doc/es/codebloc.txt
2003-07-13 14:51:56 +00:00

184 lines
5.6 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* $Id$
*/
/*
* Las siguientes partes son derechos adquiridos de sus autores individuales.
* www - http://www.harbour-project.org
*
* Copyright 2001 Ryszard Glab <rglab@imid.med.pl>
* Documentaci¢n en Ingls de codeblock.txt
*
* Copyright 2001 Alejandro de G rate <alex_degarate@hotmail.com>
* Traducci¢n al Espa¤ol de codeblock.txt
*
* Vea doc/license.txt por los trminos de la licencia.
*
*/
Implementaci¢n de Harbour de codeblocks (bloques de c¢digo)
===========================================================
Compilaci¢n de un codeblock
Durante el tiempo de Compilaci¢n, el codeblock es almacenado en la
siguiente forma:
- la cabecera
- la ristra de bytes de pcodes
La cabecera almacena informaci¢n acerca de variables locales
referenciadas.
+0: el byte pcode para _PUSHBLOCK
+1: el n£mero de bytes que definen a un codeblock
+3: el n£mero de par metros codeblock (declarados entre || en el codeblock)
+5: n£mero de variables locales usadas declaradas en el procedimiento /
funci¢n donde el codeblock es creado.
+7: La lista de las posiciones de variables locales de los procedimientos /
funciones, en la pila eval del procedimiento / funci¢n. Cada variable
local usada en un codeblock usa 2 bytes en esta lista. Cuando son
usados codeblocks anidados, entonces esta lista es creada solamente
en el codeblock m s externo.
+x: La ristra de bytes pcode, siguiendo a la cabecera.
+y: El byte pcode para _ENDBLOCK
Creaci¢n de un codeblock
========================
Cuando el opcode HB_P_PUSHBLOCK es ejecutado entonces la estructura
HB_ITEM es creada y puesta en la pila de evaluaci¢n. El tipo de item
es IT_BLOCK.
El valor de este item es un puntero a la estructura HB_CODEBLOCK.
Adicionalmente este item almacena la base de las variables est ticas
definidas para el procedimiento/funci¢n actual. - esto es usado durante
la evaluaci¢n de un codeblock cuando la evaluaci¢n es llamada desde
c¢digo desde otro m¢dulo PRG. Tambin el n£mero de par metros esperados
es almacenado.
La estructura HB_CODEBLOCK almacena un puntero a la ristra (stream)
de pcodes que es ejecutada durante la evaluaci¢n de un codeblock.
Este almacena tambin el puntero a la tabla con referencia a variables
locales. Valores de todas las variables locales definidas en un
procedimiento y usadas en un codeblock son reemplazadas con una
referencia a un valor almacenado en un pool de variables de memoria
global. Esto permite el correcto acceso a variables locales aisladas
en un codeblock devuelto desde sta funci¢n (sea directamente en una
sentencia RETURN ¢ indirectamente por asignarlo ste a una variable
est tica ¢ MEMVAR).
Este reemplazo autom tico e incondicional es requerido porque no hay
un mtodo seguro de encontrar si un codeblock ser  accedido desde
fuera de una funci¢n d¢nde ste es creado.
Cuando son usados codeblocks anidados, solamente el codeblock m s
externo crea la tabla - todo codeblock interno usa esta tabla.
Esto permite compartir la tabla entre codeblocks anidados - , la
tabla es borrada si no hay m s referencias a ella.
Esto es causado por el hecho que un codeblock interno puede ser
creado durante la evaluaci¢n del codeblock exterior cuando las
variables locales no existen como en este ejemplo:
PROCEDURE MAIN()
PRIVATE foo, bar
Test()
EVAL( foo )
EVAL( bar )
RETURN
PROCEDURE Test()
LOCAL a:='FOO', b:='BAR'
foo ={ || a + ( bar:=EVAL( {|| b} ) ) }
RETURN
Evaluaci¢n de un codeblock
==========================
Los par metros pasados a un codeblock son puestos en la pila de
evaluaci¢n antes de la evaluaci¢n del codeblock. Ellos son accedidos
exactamente igual que cualquier par metro de funci¢n. Cuando un
par metro de codeblock es referenciado, entonces su posici¢n en
la pila de evaluaci¢n es usada.
Cuando una variable local de un procedimiento es referenciada
entonces el ¡ndice dentro de la tabla de posiciones de variables
locales (copiada de la cabecera) es usada. El valor negativo es
usado como un ¡ndice para distinguirlo de la referencia a un
par metro del codeblock.
Incompatibilidad con Clipper
============================
1) Variables locales aisladas pasadas por referencia
-------------------------------------------------
Hay una peque¤a diferencia entre el manejo de las variables pasadas
por referencia en un codeblock.
El siguiente c¢digo lo explica (gracias a David G. Holm)
Function Main()
Local nTest
Local bBlock1 := MakeBlock()
Local bBlock2 := {|| DoThing( @nTest ), qout("From Main: ", nTest ) }
eval( bBlock1 )
eval( bBlock2 )
Return( NIL )
Function MakeBlock()
Local nTest
Return( {|| DoThing( @nTest ), qout("From MakeBlock: ", nTest ) } )
Function DoThing( n )
n := 42
Return( NIL )
En Clipper esto produce:
Desde MakeBlock = NIL
Desde Main = 42
En Harbour esta produce: (esta es la salida correcta, en mi opini¢n )
Desde MakeBlock = 42
Desde Main = 42
2) Alcance de variables sin declarar
---------------------------------
Considere el siguiente c¢digo:
PROCEDURE MAIN()
LOCAL cb
cb :=Detach()
? EVAL( cb, 10 )
RETURN
FUNCTION Detach()
LOCAL b:={|x| x+a}
LOCAL a:=0
RETURN b
En Clipper la variable 'a' en un codeblock tiene alcance *local* ,
sin embargo en Harbour la variable 'a' tiene un alcance *privado*.
Como resultado de ello, en Clipper este c¢digo imprimir  10 y en
Harbour este producir  "error de argumento" en la operaci¢n '+'.
Esto ser  cierto cuando la variable 'a' sea declarada como PRIVATE.
PROCEDURE MAIN()
LOCAL cb
PRIVATE a
cb := Detach()
? EVAL( cb, 10 )
RETURN
El c¢digo de arriba tambin produce 10 en Clipper (a£n si es
compilado con el switch -a ¢ -v).