2012-09-19 04:06 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* harbour/include/hbexprb.c
  * harbour/include/hbcomp.h
  * harbour/include/hbcompdf.h
  * harbour/src/compiler/hbusage.c
  * harbour/src/compiler/harbour.yyc
  * harbour/src/compiler/harbour.y
  * harbour/src/compiler/ppcomp.c
  * harbour/src/compiler/hbmain.c
  * harbour/src/compiler/cmdcheck.c
  * harbour/doc/cmpopt.txt
  * harbour/doc/xhb-diff.txt
    + added new harbour compiler switch:
         -kd => accept macros with declared symbols
      This switch allows to use declared symbols like LOCALs, STATICs
      and FIELDs in macros and macrocodeblocks (every evaluated).
    ; Please do not confuse different things. Above modification
      does not mean to that such variables are visible for macro
      compiler. It only allows to write code like:
         cbVar := {|| &cLocal + cPrivate }
      or:
         cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
      or:
         ? &cLocalPref.func&cPriv1( cPriv2 )
      etc.
      If possible then for macrocodeblocks Harbour compiler tries to
      generate early eval code in which macros are expanded when codeblock
      is created. Otherwise macros are expanded each time codeblocks are
      evaluated.
      For more information look at harbour/doc/xhb-diff.txt section:
         MACROS WITH DECLARED SYMBOLS
This commit is contained in:
Przemyslaw Czerpak
2012-09-19 02:06:42 +00:00
parent 063b013a2e
commit f5072c9fb9
12 changed files with 306 additions and 93 deletions

View File

@@ -16,6 +16,38 @@
The license applies to all entries newer than 2009-04-28.
*/
2012-09-19 04:06 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* harbour/include/hbexprb.c
* harbour/include/hbcomp.h
* harbour/include/hbcompdf.h
* harbour/src/compiler/hbusage.c
* harbour/src/compiler/harbour.yyc
* harbour/src/compiler/harbour.y
* harbour/src/compiler/ppcomp.c
* harbour/src/compiler/hbmain.c
* harbour/src/compiler/cmdcheck.c
* harbour/doc/cmpopt.txt
* harbour/doc/xhb-diff.txt
+ added new harbour compiler switch:
-kd => accept macros with declared symbols
This switch allows to use declared symbols like LOCALs, STATICs
and FIELDs in macros and macrocodeblocks (every evaluated).
; Please do not confuse different things. Above modification
does not mean to that such variables are visible for macro
compiler. It only allows to write code like:
cbVar := {|| &cLocal + cPrivate }
or:
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
or:
? &cLocalPref.func&cPriv1( cPriv2 )
etc.
If possible then for macrocodeblocks Harbour compiler tries to
generate early eval code in which macros are expanded when codeblock
is created. Otherwise macros are expanded each time codeblocks are
evaluated.
For more information look at harbour/doc/xhb-diff.txt section:
MACROS WITH DECLARED SYMBOLS
2012-09-18 18:26 UTC+0200 Viktor Szakats (harbour syenar.net)
* contrib/hbide/main.prg
! include rddads.hbx on win/linux platforms only

View File

@@ -199,6 +199,25 @@ declarations. This code illustrates it:
This behavior is not replicated in Harbour even if -kc switch is used
and Harbour optimize expressions in all declarations.
Harbour supports macro expansion for expressions with declared symbols.
This functionality can be enabled by -kd compiler switch:
-kd => accept macros with declared symbols
It only allows to write code like:
cbVar := {|| &cLocal + cPrivate }
or:
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
or:
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
etc.
If possible then for macrocodeblocks Harbour compiler tries to
generate early eval code in which macros are expanded when codeblock
is created. Otherwise macros are expanded each time codeblock is
evaluated.
This feature can be useful also in porting some other xbase compatible
code to Harbour because some compilers just like xHarbour accepted
in some limited way officially unsupported syntax with macros using
declared symbols.
Harbour has additional optimization phase which operates on generated PCODE.
It can also reduce expressions, joins jumps, removes death or meaningless
code which can appear after all other optimizations and were not optimized

View File

@@ -627,6 +627,69 @@ hb_arrayToParams() or similar function.
### MACROS WITH DECLARED SYMBOLS ###
==========================================
Harbour supports macro expansion for expressions with declared symbols.
This functionality can be enabled by -kd compiler switch:
-kd => accept macros with declared symbols
It allows to write code like:
cbVar := {|| &cLocal + cPrivate }
or:
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
or:
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
etc.
If it's possible then for macrocodeblocks Harbour compiler tries to
generate early eval code in which macros are expanded when codeblock
is created. Otherwise macros are expanded each time codeblock is
evaluated.
xHarbour has also similar extension but limited to only to macro
variables and it works only if other macros are not used in the
same expression. When more complicated examples are create xHarbour
compiler generates broken code which generate RTE or GPF during
execution. It also does not support codeblocks which contain mixed
macros and refuse to compile such code.
This example illustrates macros with declared symbols.
#ifndef __XHARBOUR__
#pragma -kd+
#endif
proc main()
memvar nPrivate
memvar cPriv1, cPriv2
local cbVar1, cbVar2
local cLocal := "10", cLocalPref := "hb_"
static cStatic := "'123xyz'"
private nPrivate := 10000
private cPriv1 := "test1", cPriv2 := "abc"
#ifndef __XHARBOUR__
cbVar1 := {|| &cLocal + nPrivate + val( &cStatic ) }
cbVar2 := {|| &cLocalPref.func&cPriv1( cPriv2, &cStatic ) }
? eval( cbVar1 )
? eval( cbVar2 )
#endif
? &cLocal + nPrivate + val( &cStatic )
cLocal := "upp"
? &cLocal.er( &cStatic )
? hb_funcTest1( cPriv2, &cStatic )
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
return
func hb_funcTest1( s1, s2 )
return s1 + ":" + s2
Above code can be compiled by xHarbour but it will not work exploiting
some problems in this compiler and generated code.
This feature can be useful also in porting some other xbase compatible
code to Harbour because some compilers just like xHarbour accepted
in some limited way officially unsupported syntax with macros using
declared symbols.
### MACRO MESSAGES ###
============================
Both compilers Harbour and xHarbour supports macros as messages.

View File

@@ -289,13 +289,13 @@ extern void hb_compErrorVParams( HB_COMP_DECL, const char * szFuncOrBlock
extern HB_EXPR_PTR hb_compErrorStatic( HB_COMP_DECL, const char *, HB_EXPR_PTR );
extern void hb_compErrorCodeblock( HB_COMP_DECL, const char * szBlock );
extern HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen );
extern void hb_compPushMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen, HB_BOOL fMacro );
/* Codeblocks */
extern void hb_compCodeBlockStart( HB_COMP_DECL, HB_BOOL bLateEval ); /* starts a codeblock creation */
extern void hb_compCodeBlockEnd( HB_COMP_DECL ); /* end of codeblock creation */
extern void hb_compCodeBlockStop( HB_COMP_DECL ); /* end of fake codeblock */
extern void hb_compCodeBlockRewind( HB_COMP_DECL ); /* restart of fake codeblock */
extern void hb_compCodeBlockStart( HB_COMP_DECL, int iEarlyEvalPass ); /* starts a codeblock creation */
extern void hb_compCodeBlockEnd( HB_COMP_DECL ); /* end of codeblock creation */
extern void hb_compCodeBlockStop( HB_COMP_DECL ); /* end of fake codeblock */
extern void hb_compCodeBlockRewind( HB_COMP_DECL ); /* restart of fake codeblock */
#endif /* HB_MACRO_SUPPORT */
@@ -383,7 +383,8 @@ extern const HB_BYTE hb_comp_pcode_len[];
#define HB_COMPFLAG_OPTJUMP 0x0100 /* -kj turn off jump optimalization */
#define HB_COMPFLAG_HB_INLINE 0x0200 /* -ki hb_inLine(...) { ... } support */
#define HB_COMPFLAG_MACROTEXT 0x0400 /* -kM turn off macrotext substitution */
#define HB_COMPFLAG_USERCP 0x0800 /* -kU strings in user encoding */
#define HB_COMPFLAG_USERCP 0x0800 /* -ku strings in user encoding */
#define HB_COMPFLAG_MACRODECL 0x1000 /* -kd accept macros with declared symbols */
#define HB_COMP_ISSUPPORTED(flag) ( HB_COMP_PARAM->supported & (flag) )
@@ -393,6 +394,7 @@ extern const HB_BYTE hb_comp_pcode_len[];
#define HB_SUPPORT_EXTOPT ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_EXTOPT) )
#define HB_SUPPORT_MACROTEXT ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_MACROTEXT) )
#define HB_SUPPORT_USERCP ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_USERCP) )
#define HB_SUPPORT_MACRODECL ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_MACRODECL) )
#if defined( HB_MACRO_SUPPORT )
# define HB_MACRO_GENFLAGS HB_COMPFLAG_RT_MACRO

View File

@@ -511,13 +511,13 @@ typedef struct __FUNC
HB_BYTE * pCode; /* pointer to a memory block where pcode is stored */
HB_SIZE nPCodeSize; /* total memory size for pcode */
HB_SIZE nPCodePos; /* actual pcode offset */
int iStaticsBase; /* base for this function statics */
int iFuncSuffix; /* function suffix for multiple static functions with the same name */
HB_SIZE * pNOOPs; /* pointer to the NOOP array */
HB_SIZE * pJumps; /* pointer to the Jumps array */
HB_SIZE nNOOPs; /* NOOPs Counter */
HB_SIZE nJumps; /* Jumps Counter */
HB_BOOL bLateEval; /* HB_TRUE if accessing of declared (compile time) variables is allowed */
int iStaticsBase; /* base for this function statics */
int iFuncSuffix; /* function suffix for multiple static functions with the same name */
int iEarlyEvalPass; /* !=0 if early evaluaded block is compiled - accessing of declared (compile time) variables is limited */
HB_BOOL fVParams; /* HB_TRUE if variable number of parameters is used */
HB_BOOL bError; /* error during function compilation */
HB_BOOL bBlock; /* HB_TRUE if simple codeblock body is compiled */

View File

@@ -130,7 +130,7 @@ static HB_EXPR_FUNC( hb_compExprUseNegate );
#if defined( HB_MACRO_SUPPORT )
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_COMP_DECL );
#else
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_BOOL, HB_COMP_DECL );
static HB_BOOL hb_compExprCodeblockPush( HB_EXPR_PTR, int, HB_COMP_DECL );
static void hb_compExprCodeblockEarly( HB_EXPR_PTR, HB_COMP_DECL );
static void hb_compExprCodeblockExtPush( HB_EXPR_PTR pSelf, HB_COMP_DECL );
#endif
@@ -394,20 +394,23 @@ static HB_EXPR_FUNC( hb_compExprUseString )
break;
case HB_EA_PUSH_PCODE:
{
#if ! defined( HB_MACRO_SUPPORT )
if( !HB_SUPPORT_MACROTEXT )
HB_GEN_FUNC2( PushString, pSelf->value.asString.string,
pSelf->nLength + 1 );
else
hb_compPushMacroText( HB_COMP_PARAM,
pSelf->value.asString.string,
pSelf->nLength, HB_FALSE );
#else
HB_GEN_FUNC2( PushString, pSelf->value.asString.string,
pSelf->nLength + 1 );
#if ! defined( HB_MACRO_SUPPORT )
if( HB_SUPPORT_MACROTEXT &&
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asString.string,
pSelf->nLength ) )
#else
if( hb_macroIsValidMacroText( pSelf->value.asString.string,
pSelf->nLength ) )
#endif
{
HB_GEN_FUNC1( PCode1, HB_P_MACROTEXT );
}
#endif
break;
}
case HB_EA_POP_PCODE:
@@ -456,7 +459,7 @@ static HB_EXPR_FUNC( hb_compExprUseCodeblock )
/* early evaluation of a macro */
hb_compExprCodeblockEarly( pSelf, HB_COMP_PARAM );
else
hb_compExprCodeblockPush( pSelf, HB_TRUE, HB_COMP_PARAM );
hb_compExprCodeblockPush( pSelf, 0, HB_COMP_PARAM );
#endif
break;
}
@@ -1591,7 +1594,13 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
/* simple macro variable expansion: &variable
* 'szMacro' is a variable name
*/
#if ! defined( HB_MACRO_SUPPORT )
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
#else
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
#endif
}
else
{
@@ -1604,11 +1613,12 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
* local, static or field.
*/
#if ! defined( HB_MACRO_SUPPORT )
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ) );
#endif
hb_compPushMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ), HB_TRUE );
#else
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
#endif
}
}
@@ -1676,7 +1686,13 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
/* simple macro variable expansion: &variable
* 'szMacro' is a variable name
*/
#if ! defined( HB_MACRO_SUPPORT )
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
#else
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
#endif
}
else
{
@@ -1689,11 +1705,12 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
* local, static or field.
*/
#if ! defined( HB_MACRO_SUPPORT )
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ) );
#endif
hb_compPushMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ), HB_TRUE );
#else
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
#endif
}
}
/* compile & run - macro compiler will generate pcode to pop a value
@@ -4472,7 +4489,7 @@ static HB_EXPR_FUNC( hb_compExprUsePreDec )
#if defined( HB_MACRO_SUPPORT )
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_COMP_DECL )
#else
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_COMP_DECL )
static HB_BOOL hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, int iEarlyEvalPass, HB_COMP_DECL )
#endif
{
HB_EXPR_PTR pExpr, pNext;
@@ -4486,7 +4503,7 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
HB_PCODE_DATA->fVParams =
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
#else
hb_compCodeBlockStart( HB_COMP_PARAM, bLateEval );
hb_compCodeBlockStart( HB_COMP_PARAM, iEarlyEvalPass );
HB_COMP_PARAM->functions.pLast->fVParams =
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
@@ -4548,7 +4565,7 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
else
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
#else
if( pNext && bLateEval )
if( pNext && ( iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL ) )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
else
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
@@ -4559,10 +4576,16 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
#if defined( HB_MACRO_SUPPORT )
hb_macroCodeBlockEnd( HB_COMP_PARAM );
#else
if( bLateEval )
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 )
{
hb_compCodeBlockEnd( HB_COMP_PARAM );
return HB_TRUE;
}
else
{
hb_compCodeBlockRewind( HB_COMP_PARAM );
return HB_FALSE;
}
#endif
}
@@ -4603,11 +4626,18 @@ static void hb_compExprCodeblockEarly( HB_EXPR_PTR pSelf, HB_COMP_DECL )
/* everything else is macro compiled at runtime
* {|| &variable+1} => &( '{|| &variable+1}' )
*/
hb_compExprCodeblockPush( pSelf, HB_FALSE, HB_COMP_PARAM );
pExpr = hb_compExprNewMacro( hb_compExprNewString( pSelf->value.asCodeblock.string, pSelf->nLength, HB_FALSE, HB_COMP_PARAM ), 0, NULL, HB_COMP_PARAM );
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
HB_COMP_EXPR_FREE( pExpr );
hb_compCodeBlockStop( HB_COMP_PARAM );
if( !hb_compExprCodeblockPush( pSelf, 1, HB_COMP_PARAM ) )
{
HB_BOOL fMacroText = ( HB_COMP_PARAM->supported & HB_COMPFLAG_MACROTEXT ) != 0;
HB_COMP_PARAM->supported |= HB_COMPFLAG_MACROTEXT;
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = 2;
pExpr = hb_compExprNewMacro( hb_compExprNewString( pSelf->value.asCodeblock.string, pSelf->nLength, HB_FALSE, HB_COMP_PARAM ), 0, NULL, HB_COMP_PARAM );
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
HB_COMP_EXPR_FREE( pExpr );
hb_compCodeBlockStop( HB_COMP_PARAM );
if( !fMacroText )
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACROTEXT;
}
}
}
#endif /*HB_MACRO_SUPPORT*/

View File

@@ -411,6 +411,17 @@ static void hb_compChkEnvironVar( HB_COMP_DECL, const char *szSwitch )
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACROTEXT;
break;
case 'd':
case 'D':
if( s[i] == '-' )
{
i++;
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACRODECL;
}
else
HB_COMP_PARAM->supported |= HB_COMPFLAG_MACRODECL;
break;
case 'r':
case 'R':
if( s[i] == '-' )

View File

@@ -1038,7 +1038,7 @@ CodeBlock : BlockHead
HB_CBVAR_PTR pVar;
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
$<sNumber>2 = HB_COMP_PARAM->lastLine;
hb_compCodeBlockStart( HB_COMP_PARAM, HB_TRUE );
hb_compCodeBlockStart( HB_COMP_PARAM, 0 );
HB_COMP_PARAM->functions.pLast->funFlags |= FUN_EXTBLOCK;
HB_COMP_PARAM->functions.pLast->fVParams =
( $1->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;

View File

@@ -6110,7 +6110,7 @@ yyreduce:
HB_CBVAR_PTR pVar;
(yyval.sNumber) = HB_COMP_PARAM->functions.pLast->nPCodePos;
(yyvsp[(2) - (2)].sNumber) = HB_COMP_PARAM->lastLine;
hb_compCodeBlockStart( HB_COMP_PARAM, HB_TRUE );
hb_compCodeBlockStart( HB_COMP_PARAM, 0 );
HB_COMP_PARAM->functions.pLast->funFlags |= FUN_EXTBLOCK;
HB_COMP_PARAM->functions.pLast->fVParams =
( (yyvsp[(1) - (2)].asExpr)->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;

View File

@@ -733,7 +733,7 @@ PVAR hb_compVariableFind( HB_COMP_DECL, const char * szVarName, int * piPos, int
*/
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_ILLEGAL_INIT, "(b)", szVarName );
}
else if( fBlock )
else if( fBlock && HB_COMP_PARAM->functions.pLast->iEarlyEvalPass < 2 )
{
/* We want to access a local variable defined in a function
* that owns this codeblock. We cannot access this variable in
@@ -892,10 +892,12 @@ int hb_compVariableScope( HB_COMP_DECL, const char * szVarName )
return iScope;
}
HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen )
void hb_compPushMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen, HB_BOOL fMacro )
{
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
HB_BOOL fFound = HB_FALSE;
HB_SIZE n = 0;
int iParts = 0;
while( n < nLen )
{
@@ -919,7 +921,7 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
if( ch >= 'a' && ch <= 'z' )
szSymName[ iSize++ ] = ch - ( 'a' - 'A' );
else if( ch == '_' || ( ch >= 'A' && ch <= 'Z' ) ||
( ch >= '0' && ch <= '9' ) )
( iSize > 0 && ch >= '0' && ch <= '9' ) )
szSymName[ iSize++ ] = ch;
else
break;
@@ -928,7 +930,10 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
if( iSize )
{
const char * pszVarName;
szSymName[ iSize ] = '\0';
pszVarName = hb_compIdentifierNew( HB_COMP_PARAM, szSymName, HB_IDENT_COPY );
/* NOTE: All variables are assumed memvars in macro compiler -
* there is no need to check for a valid name but to be Clipper
@@ -937,20 +942,59 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
* Only MEMVAR or undeclared (memvar will be assumed)
* variables can be used in macro text.
*/
fFound = HB_TRUE;
iScope = hb_compVariableScope( HB_COMP_PARAM, szSymName );
if( iScope != HB_VS_UNDECLARED && !( iScope & HB_VS_LOCAL_MEMVAR ) )
iScope = hb_compVariableScope( HB_COMP_PARAM, pszVarName );
if( iScope == HB_VS_UNDECLARED || ( iScope & HB_VS_LOCAL_MEMVAR ) )
{
hb_compErrorMacro( HB_COMP_PARAM, szText );
break;
fFound = HB_TRUE;
if( fMacro && iScope == HB_VS_UNDECLARED )
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, pszVarName, NULL );
}
else
{
if( HB_SUPPORT_MACRODECL )
{
HB_SIZE nPrefix = n - iSize - 1;
if( nPrefix > 0 )
{
char * pszPrefix = ( char * ) hb_xgrab( nPrefix + 1 );
memcpy( pszPrefix, szText, nPrefix );
pszPrefix[ nPrefix ] = '\0';
hb_compGenPushString( pszPrefix, nPrefix + 1, HB_COMP_PARAM );
hb_xfree( pszPrefix );
if( iParts++ > 0 )
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
}
hb_compGenPushVar( pszVarName, HB_COMP_PARAM );
if( iParts++ > 0 )
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
if( n < nLen && szText[ n ] == '.' )
++n;
szText += n;
nLen -= n;
n = 0;
}
else
{
hb_compErrorMacro( HB_COMP_PARAM, szText );
break;
}
}
}
else if( ! HB_SUPPORT_HARBOUR )
fFound = HB_TRUE; /* always macro substitution in Clipper */
}
}
if( nLen > 0 )
{
hb_compGenPushString( szText, nLen + 1, HB_COMP_PARAM );
if( iParts > 0 )
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
}
return fFound;
if( fFound )
hb_compGenPCode1( HB_P_MACROTEXT, HB_COMP_PARAM );
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
}
@@ -1844,7 +1888,7 @@ static PFUNCTION hb_compFunctionNew( HB_COMP_DECL, const char * szName, HB_SYMBO
pFunc->szName = szName;
pFunc->cScope = cScope;
pFunc->iStaticsBase = HB_COMP_PARAM->iStaticCnt;
pFunc->bLateEval = HB_TRUE;
pFunc->iEarlyEvalPass = 0;
pFunc->fVParams = HB_FALSE;
pFunc->bError = HB_FALSE;
@@ -2498,7 +2542,7 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
* Clipper always assumes a memvar variable if undeclared variable
* is popped (a value is asssigned to a variable).
*/
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_HARBOUR ) )
if( HB_SUPPORT_HARBOUR )
bGenCode = HB_COMP_PARAM->fForceMemvars; /* harbour compatibility */
else
bGenCode = ( HB_COMP_PARAM->fForceMemvars || bPCode == HB_P_POPVARIABLE );
@@ -2507,7 +2551,8 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
{
/* -v switch was used -> assume it is a memvar variable
*/
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL );
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL )
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL );
if( bPCode == HB_P_POPVARIABLE )
bPCode = HB_P_POPMEMVAR;
@@ -2516,7 +2561,7 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
else
bPCode = HB_P_PUSHMEMVARREF;
}
else
else if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL )
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, szVarName, NULL );
hb_compGenVarPCode( bPCode, szVarName, HB_COMP_PARAM );
@@ -2582,18 +2627,24 @@ void hb_compGenMessageData( const char * szMsg, HB_BOOL bIsObject, HB_COMP_DECL
hb_compGenMessage( hb_compIdentifierNew( HB_COMP_PARAM, szResult, HB_IDENT_COPY ), bIsObject, HB_COMP_PARAM );
}
static void hb_compCheckEarlyMacroEval( HB_COMP_DECL, const char *szVarName )
static void hb_compCheckEarlyMacroEval( HB_COMP_DECL, const char *szVarName, int iScope )
{
int iScope = hb_compVariableScope( HB_COMP_PARAM, szVarName );
if( iScope == HB_VS_CBLOCAL_VAR ||
/* iScope == HB_VS_LOCAL_VAR || */
/* iScope == HB_VS_LOCAL_VAR || */ /* codeblock parameters */
iScope == HB_VS_STATIC_VAR ||
iScope == HB_VS_GLOBAL_STATIC ||
iScope == HB_VS_LOCAL_FIELD ||
iScope == HB_VS_GLOBAL_FIELD )
{
hb_compErrorCodeblock( HB_COMP_PARAM, szVarName );
/* Disable early evaluation if codeblock contains macros and
* declared variables, i.e. {|x| cLocal + &cPriv }
* and support for macros with declared symbols is enabled.
*/
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 &&
HB_SUPPORT_MACRODECL )
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = 0;
else
hb_compErrorCodeblock( HB_COMP_PARAM, szVarName );
}
}
@@ -2612,16 +2663,12 @@ void hb_compGenPopVar( const char * szVarName, HB_COMP_DECL ) /* generates the p
int iVar, iScope;
PVAR pVar;
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
{
/* pseudo-generation of pcode for a codeblock with macro symbol */
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
return;
}
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
if( pVar )
{
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
switch( iScope )
{
case HB_VS_LOCAL_VAR:
@@ -2668,12 +2715,12 @@ void hb_compGenPopVar( const char * szVarName, HB_COMP_DECL ) /* generates the p
break;
default:
/* undeclared variable */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName );
pVar = NULL;
break;
}
}
else
if( !pVar )
{ /* undeclared variable */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName );
}
@@ -2696,16 +2743,12 @@ void hb_compGenPushVar( const char * szVarName, HB_COMP_DECL )
int iVar, iScope;
PVAR pVar;
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
{
/* pseudo-generation of pcode for a codeblock with macro symbol */
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
return;
}
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
if( pVar )
{
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
switch( iScope )
{
case HB_VS_LOCAL_VAR:
@@ -2742,12 +2785,12 @@ void hb_compGenPushVar( const char * szVarName, HB_COMP_DECL )
break;
default:
/* undeclared variable */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName );
pVar = NULL;
break;
}
}
else
if( !pVar )
{ /* undeclared variable */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName );
}
@@ -2758,16 +2801,12 @@ void hb_compGenPushVarRef( const char * szVarName, HB_COMP_DECL ) /* generates t
int iVar, iScope;
PVAR pVar;
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
{
/* pseudo-generation of pcode for a codeblock with macro symbol */
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
return;
}
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
if( pVar )
{
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
switch( iScope )
{
case HB_VS_LOCAL_VAR:
@@ -2796,13 +2835,11 @@ void hb_compGenPushVarRef( const char * szVarName, HB_COMP_DECL ) /* generates t
break;
default:
/* undeclared variable */
/* field cannot be passed by the reference - assume the memvar */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName );
break;
pVar = NULL;
}
}
else
if( !pVar )
{ /* undeclared variable */
/* field cannot be passed by the reference - assume the memvar */
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName );
@@ -3470,13 +3507,13 @@ static void hb_compLineNumberDefEnd( HB_COMP_DECL )
/*
* Start a new fake-function that will hold pcodes for a codeblock
*/
void hb_compCodeBlockStart( HB_COMP_DECL, HB_BOOL bLateEval )
void hb_compCodeBlockStart( HB_COMP_DECL, int iEarlyEvalPass )
{
PFUNCTION pBlock;
pBlock = hb_compFunctionNew( HB_COMP_PARAM, NULL, HB_FS_STATIC | HB_FS_LOCAL );
pBlock->pOwner = HB_COMP_PARAM->functions.pLast;
pBlock->bLateEval = bLateEval;
pBlock = hb_compFunctionNew( HB_COMP_PARAM, NULL, HB_FS_STATIC | HB_FS_LOCAL );
pBlock->pOwner = HB_COMP_PARAM->functions.pLast;
pBlock->iEarlyEvalPass = iEarlyEvalPass;
HB_COMP_PARAM->functions.pLast = pBlock;
}
@@ -3707,6 +3744,18 @@ void hb_compCodeBlockRewind( HB_COMP_DECL )
pCodeblock->pJumps = NULL;
pCodeblock->nJumps = 0;
}
while( pCodeblock->pDetached )
{
PVAR pVar = pCodeblock->pDetached;
pCodeblock->pDetached = pVar->pNext;
hb_xfree( pVar );
}
while( pCodeblock->pLocals )
{
PVAR pVar = pCodeblock->pLocals;
pCodeblock->pLocals = pVar->pNext;
hb_xfree( pVar );
}
}
/* ************************************************************************* */

View File

@@ -140,8 +140,9 @@ void hb_compPrintModes( HB_COMP_DECL )
"\n s[-] allow indexed assignment on all types",
"\n x[-] extended Xbase++ mode",
"\n u[-] strings in user encoding",
"\n j[+] turn off jump optimization in pcode",
"\n d[-] accept macros with declared symbols",
"\n m[+] turn off macrotext substitution",
"\n j[+] turn off jump optimization in pcode",
"\n ? this info",
"\n"
};
@@ -154,8 +155,10 @@ void hb_compPrintModes( HB_COMP_DECL )
HB_COMPFLAG_RT_MACRO,
HB_COMPFLAG_ARRSTR,
HB_COMPFLAG_XBASE,
~HB_COMPFLAG_OPTJUMP,
HB_COMPFLAG_USERCP,
HB_COMPFLAG_MACRODECL,
~HB_COMPFLAG_MACROTEXT,
~HB_COMPFLAG_OPTJUMP,
};
int iLine;

View File

@@ -291,6 +291,10 @@ static HB_BOOL hb_pp_CompilerSwitch( void * cargo, const char * szSwitch,
iFlag = HB_COMPFLAG_MACROTEXT;
iValue = !iValue;
break;
case 'd':
case 'D':
iFlag = HB_COMPFLAG_MACRODECL;
break;
case 's':
case 'S':
iFlag = HB_COMPFLAG_ARRSTR;