diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 2bcdae4d25..44f03887f0 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,15 @@ +19991117-13:05 GMT+1 Ryszard Glab + + *source/compiler/harbour.y + *source/compiler/harbour.l + *source/compiler/harbour.c + *source/compiler/expropt.c + * corrected support for expression->identifier syntax + * corrected optimization for division operator + + *include/compiler.h + * removed declaration no longer needed + 19991117-10:51 GMT+1 Victor Szel * source/compiler/expropt.c ! Fixed the compile-time calculation of numeric operations with results diff --git a/harbour/include/compiler.h b/harbour/include/compiler.h index 691156d794..ec0b0f4159 100644 --- a/harbour/include/compiler.h +++ b/harbour/include/compiler.h @@ -219,23 +219,6 @@ extern PCOMSYMBOL KillSymbol( PCOMSYMBOL ); /* releases all memory allocated #define FUN_USES_LOCAL_PARAMS 16 /* parameters are declared using () */ #define FUN_WITH_RETURN 32 /* there was RETURN statement in previous line */ -/* Support for aliased expressions - */ -typedef struct _ALIASID -{ - char type; - union - { - int iAlias; - char * szAlias; - } alias; - struct _ALIASID * pPrev; -} ALIASID, *ALIASID_PTR; - -#define ALIAS_NUMBER 1 -#define ALIAS_NAME 2 -#define ALIAS_EVAL 3 - typedef struct __EXTERN { char * szName; @@ -260,32 +243,8 @@ typedef struct __ELSEIF struct __ELSEIF * pNext; } _ELSEIF, * PELSEIF; /* support structure for else if pcode fixups */ -/* Support for parenthesized expressions +/* TODO: clear the functions name space */ -typedef struct _EXPLIST -{ - BYTE * prevPCode; /* pcode buffer used at the start of expression */ - ULONG prevSize; - ULONG prevPos; - BYTE * exprPCode; /* pcode buffer for current expression */ - ULONG exprSize; - struct _EXPLIST *pPrev; /* previous expression in the list */ - struct _EXPLIST *pNext; /* next expression in the list */ -} EXPLIST, *EXPLIST_PTR; - -/* production related functions */ -void AliasAddInt( int ); -void AliasAddExp( void ); -void AliasAddStr( char * ); -void AliasPush( void ); -void AliasPop( void ); -void AliasSwap( void ); -void AliasAdd( ALIASID_PTR ); -void AliasRemove( void ); - -void ExpListPush( void ); /* pushes the new expression on the stack */ -void ExpListPop( int ); /* pops previous N expressions */ - PFUNCTION hb_compAddFunCall( char * szFuntionName ); void hb_compAddExtern( char * szExternName ); /* defines a new extern name */ void hb_compAddVar( char * szVarName, char cType ); /* add a new param, local, static variable to a function definition or a public or private */ @@ -334,6 +293,8 @@ void hb_compGenPushLong( long lNumber ); /* Pushes a long number on the void hb_compGenPushNil( void ); /* Pushes nil on the virtual machine stack */ void hb_compGenPushString( char * szText, ULONG ulLen ); /* Pushes a string on the virtual machine stack */ void hb_compPushSymbol( char * szSymbolName, int iIsFunction ); /* Pushes a symbol on to the Virtual machine stack */ +void hb_compGenPushAliasedVar( char *, BOOL, char *, long ); +void hb_compGenPopAliasedVar( char *, BOOL, char *, long ); /* Codeblocks */ void hb_compCodeBlockStart( void ); /* starts a codeblock creation */ diff --git a/harbour/source/compiler/expropt.c b/harbour/source/compiler/expropt.c index 69cb0c1ead..92e85e34ca 100644 --- a/harbour/source/compiler/expropt.c +++ b/harbour/source/compiler/expropt.c @@ -1755,16 +1755,20 @@ static HB_EXPR_FUNC( hb_compExprUseList ) ULONG ulCount; ulCount = hb_compExprListReduce( pSelf ); +/* if( ulCount == 1 && pSelf->value.asList.pExprList->ExprType <= HB_ET_VARIABLE ) { + */ /* replace the list with a simple expression */ +/* HB_EXPR_PTR pExpr = pSelf; pSelf = pSelf->value.asList.pExprList; pExpr->value.asList.pExprList = NULL; hb_compExprDelete( pExpr ); } + */ } break; @@ -1774,7 +1778,12 @@ static HB_EXPR_FUNC( hb_compExprUseList ) case HB_EA_LVALUE: if( hb_compExprListLen( pSelf ) == 1 ) + { + /* For example: + * ( a ) := 4 + */ hb_compErrorLValue( pSelf->value.asList.pExprList ); + } else hb_compErrorLValue( pSelf ); break; @@ -2082,12 +2091,114 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) case HB_EA_ARRAY_AT: case HB_EA_ARRAY_INDEX: case HB_EA_LVALUE: + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; + BOOL bReduced = FALSE; + + if( pAlias->ExprType == HB_ET_LIST ) + { + pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); + bReduced = TRUE; + } + + if( pAlias->ExprType == HB_ET_SYMBOL ) + { + /* + * myalias->var + * FIELD->var + * MEMVAR->var + * + * NOTE: TRUE = push also alias + */ + hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, TRUE, pAlias->value.asSymbol, 0 ); + } + else if( pAlias->ExprType == HB_ET_NUMERIC ) + { + /* numeric alias + * 2->var + * + * NOTE: only integer (long) values are allowed + */ + if( pAlias->value.asNum.NumType == HB_ET_LONG ) + hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, TRUE, NULL, pAlias->value.asNum.lVal ); + else + hb_compErrorAlias( pAlias ); + } + else if( bReduced ) + { + /* + * ( expression )->var + * + * NOTE: FALSE = don't push alias value + */ + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, FALSE, NULL, 0 ); + } + else + hb_compErrorAlias( pAlias ); + } + break; + case HB_EA_POP_PCODE: + { + HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; + BOOL bReduced = FALSE; + + if( pAlias->ExprType == HB_ET_LIST ) + { + pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); + bReduced = TRUE; + } + + if( pAlias->ExprType == HB_ET_SYMBOL ) + { + /* + * myalias->var + * FIELD->var + * MEMVAR->var + */ + hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, TRUE, pAlias->value.asSymbol, 0 ); + } + else if( pAlias->ExprType == HB_ET_NUMERIC ) + { + /* numeric alias + * 2->var + * + * NOTE: only integer (long) values are allowed + */ + if( pAlias->value.asNum.NumType == HB_ET_LONG ) + hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, TRUE, NULL, pAlias->value.asNum.lVal ); + else + hb_compErrorAlias( pAlias ); + } + else if( bReduced ) + { + /* + * ( expression )->var + * + * NOTE: FALSE = don't push alias value + */ + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, FALSE, NULL, 0 ); + } + else + hb_compErrorAlias( pAlias ); + } + break; + + case HB_EA_PUSH_POP: case HB_EA_STATEMENT: - hb_compWarnMeaningless( pSelf ); + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); + break; + case HB_EA_DELETE: + hb_compExprDelete( pSelf->value.asAlias.pAlias ); + /* NOTE: variable name is not released now */ break; } return pSelf; @@ -4322,6 +4433,7 @@ static HB_EXPR_FUNC( hb_compExprUseDiv ) pSelf->value.asNum.bDec = 2; /* TODO: See NOTE 1 */ pSelf->value.asNum.NumType = HB_ET_DOUBLE; } + pSelf->ExprType = HB_ET_NUMERIC; } break; @@ -4332,6 +4444,7 @@ static HB_EXPR_FUNC( hb_compExprUseDiv ) pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.NumType = HB_ET_DOUBLE; pSelf->value.asNum.bDec = 2; /* TODO: See NOTE 1 */ + pSelf->ExprType = HB_ET_NUMERIC; } break; @@ -4350,8 +4463,10 @@ static HB_EXPR_FUNC( hb_compExprUseDiv ) dVal = ( double ) pLeft->value.asNum.lVal / pRight->value.asNum.dVal; pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = 2; /* TODO: See NOTE 1 */ + } pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->ExprType = HB_ET_NUMERIC; } /* TODO: NOTE 1 Clipper manages to print the default number of decimal @@ -4362,11 +4477,14 @@ static HB_EXPR_FUNC( hb_compExprUseDiv ) for HB_DEC_DEFAULT when formatting numbers and print the current default number of decimal digits. */ - } - pSelf->ExprType = HB_ET_NUMERIC; - pSelf->ValType = HB_EV_NUMERIC; - HB_EXPR_USE( pLeft, HB_EA_DELETE ); - HB_EXPR_USE( pRight, HB_EA_DELETE ); + } /* switch bType*/ + if( pSelf->ExprType == HB_ET_NUMERIC ) + { + /* The expression was reduced - delete old components */ + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprDelete( pLeft ); + hb_compExprDelete( pRight ); + } } else { diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 2bb7d794cb..b41bc147a8 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -118,12 +118,10 @@ BOOL hb_comp_bDontGenLineNum = FALSE; /* suppress line number generation */ LONG hb_comp_lLastPushPos = -1; /* position of last push pcode */ ULONG hb_comp_ulLastLinePos = 0; /* position of last opcode with line number */ ULONG hb_comp_ulMessageFix = 0; /* Position of the message which needs to be changed */ -ALIASID_PTR hb_comp_pAliasId = NULL; int hb_comp_iStaticCnt = 0; /* number of defined statics variables on the PRG */ BOOL hb_comp_bExternal = FALSE; PTR_LOOPEXIT hb_comp_pLoops = NULL; PEXTERN hb_comp_pExterns = NULL; -EXPLIST_PTR hb_comp_pExprList = NULL; /* stack used for parenthesized expressions */ int hb_comp_iVarScope = VS_LOCAL; /* holds the scope for next variables to be defined */ /* different values for hb_comp_iVarScope */ @@ -1575,79 +1573,6 @@ PCOMSYMBOL hb_compAddSymbol( char * szSymbolName, USHORT * pwPos ) return pSym; } -/* Adds new alias to the alias stack - */ -void AliasAdd( ALIASID_PTR pAlias ) -{ - pAlias->pPrev = hb_comp_pAliasId; - hb_comp_pAliasId = pAlias; -} - -/* Restores previously selected alias - */ -void AliasRemove( void ) -{ - ALIASID_PTR pAlias = hb_comp_pAliasId; - - hb_comp_pAliasId = hb_comp_pAliasId->pPrev; - hb_xfree( pAlias ); -} - -/* Adds an integer workarea number into alias stack - */ -void AliasAddInt( int iWorkarea ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_NUMBER; - pAlias->alias.iAlias = iWorkarea; - AliasAdd( pAlias ); -} - -/* Adds an expression into alias stack - */ -void AliasAddExp( void ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_EVAL; - AliasAdd( pAlias ); -} - -/* Adds an alias name into alias stack - */ -void AliasAddStr( char * szAlias ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_NAME; - pAlias->alias.szAlias = szAlias; - AliasAdd( pAlias ); -} - -/* Generates pcodes to store the current workarea number - */ -void AliasPush( void ) -{ - hb_compGenPCode1( HB_P_PUSHALIAS ); -} - -/* Generates pcodes to select the workarea number using current value - * from the eval stack - */ -void AliasPop( void ) -{ - hb_compGenPCode1( HB_P_POPALIAS ); -} - -/* Generates pcodes to swap two last items from the eval stack. - * Last item (after swaping) is next popped as current workarea - */ -void AliasSwap( void ) -{ - hb_compGenPCode1( HB_P_SWAPALIAS ); -} - void Duplicate( void ) { hb_compGenPCode1( HB_P_DUPLICATE ); @@ -1661,98 +1586,6 @@ void DupPCode( ULONG ulStart ) /* duplicates the current generated pcode from an hb_compGenPCode1( hb_comp_functions.pLast->pCode[ ulStart + w ] ); } -/* - * Starts a new expression in the parenthesized epressions list - */ -void ExpListPush( void ) -{ - EXPLIST_PTR pExp = ( EXPLIST_PTR ) hb_xgrab( sizeof( EXPLIST ) ); - - pExp->pNext = pExp->pPrev = NULL; - - /* Store the previous state on the stack */ - if( hb_comp_pExprList ) - { - hb_comp_pExprList->pNext = pExp; - pExp->pPrev = hb_comp_pExprList; - /* save currently used pcode buffer */ - hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; - hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; - } - hb_comp_pExprList = pExp; - - /* store current pcode buffer */ - pExp->prevPCode = hb_comp_functions.pLast->pCode; - pExp->prevSize = hb_comp_functions.pLast->lPCodeSize; - pExp->prevPos = hb_comp_functions.pLast->lPCodePos; - - /* and create the new one */ - hb_comp_functions.pLast->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); - hb_comp_functions.pLast->lPCodeSize = PCODE_CHUNK; - hb_comp_functions.pLast->lPCodePos = 0; - - pExp->exprPCode = hb_comp_functions.pLast->pCode; -} - -/* - * Pops specified number of expressions from the stack - */ -void ExpListPop( int iExpCount ) -{ - EXPLIST_PTR pExp, pDel; - - /* save currently used pcode buffer */ - hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; - hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; - - /* find the first expression in the list */ - while( --iExpCount ) - hb_comp_pExprList = hb_comp_pExprList->pPrev; - - /* return to the original pcode buffer */ - hb_comp_functions.pLast->pCode = hb_comp_pExprList->prevPCode; - hb_comp_functions.pLast->lPCodeSize = hb_comp_pExprList->prevSize; - hb_comp_functions.pLast->lPCodePos = hb_comp_pExprList->prevPos; - - pExp = hb_comp_pExprList; - if( hb_comp_pExprList->pPrev ) - { - hb_comp_pExprList = hb_comp_pExprList->pPrev; - hb_comp_pExprList->pNext = NULL; - } - else - hb_comp_pExprList = NULL; - - while( pExp ) - { - if( pExp->exprSize ) - { - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - if( pExp->pNext ) - hb_compGenPCode1( HB_P_POP ); - } - else - { - /* exprN, , exprN1 - * in this context empty expression is not allowed - * - * NOTE: - * We don't have to generate this error - it is safe to continue - * pcode generation - in this case an empty expression will not - * generate any opcode - */ - hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ")", NULL ); - } - - hb_xfree( pExp->exprPCode ); - - pDel = pExp; - pExp = pExp->pNext; - hb_xfree( pDel ); - } -} - - /* * Function generates passed pcode for passed database field */ @@ -1994,118 +1827,6 @@ void hb_compGenExterns( void ) /* generates the symbols for the EXTERN names */ } } -/* This function generates pcodes for IIF( expr1, expr2, expr3 ) - * or IF( expr1, expr2, expr3 ) - * - * NOTE: - * 'IF' followed by parenthesized expression containing 3 expressions - * is always interpreted as IF inlined - it is not possible to distinguish - * it from IF( expr1, expr2, expr3 ); ENDIF syntax - * (This behaviour is Clipper compatible) - */ -void GenIfInline( void ) -{ - EXPLIST_PTR pExp, pDel; - int iExpCount = 3; /* We are expecting 3 expressions here */ - BOOL bhb_compGenPCode; - - /* save currently used pcode buffer */ - hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; - hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; - - /* find the first expression in the list */ - while( --iExpCount ) - hb_comp_pExprList = hb_comp_pExprList->pPrev; - - /* return to the original pcode buffer */ - hb_comp_functions.pLast->pCode = hb_comp_pExprList->prevPCode; - hb_comp_functions.pLast->lPCodeSize = hb_comp_pExprList->prevSize; - hb_comp_functions.pLast->lPCodePos = hb_comp_pExprList->prevPos; - - /* Update the pointer for nested or next expressions */ - pExp = hb_comp_pExprList; - if( hb_comp_pExprList->pPrev ) - { - hb_comp_pExprList = hb_comp_pExprList->pPrev; - hb_comp_pExprList->pNext = NULL; - } - else - hb_comp_pExprList = NULL; - - bhb_compGenPCode = TRUE; - pDel = pExp; /* save it for later use */ - - /* pExp points now to pcode buffer for logical condition - */ - if( pExp->exprSize == 0 ) - { - /* The logical condition have to be specified. - * If it is empty then generate the syntax error - */ - hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ",", NULL ); - } - else if( pExp->exprSize == 1 ) - { - /* one byte opcode for logical condition - check if it is TRUE or FALSE - */ - if( pExp->exprPCode[ 0 ] == HB_P_TRUE ) - { - /* move to the second expression */ - pExp = pExp->pNext; - if( pExp->exprSize ) - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - hb_compGenPushNil(); /* IIF have to return some value */ - bhb_compGenPCode = FALSE; - } - else if( pExp->exprPCode[ 0 ] == HB_P_FALSE ) - { - /* move to the third expression */ - pExp = pExp->pNext; - pExp = pExp->pNext; - if( pExp->exprSize ) - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - hb_compGenPushNil(); /* IIF have to return some value */ - bhb_compGenPCode = FALSE; - } - } - - if( bhb_compGenPCode ) - { - /* generate pcodes for all expressions - */ - LONG lPosFalse, lPosEnd; - - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - lPosFalse = hb_compGenJumpFalse( 0 ); - - pExp = pExp->pNext; - if( pExp->exprSize ) - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - hb_compGenPushNil(); /* IIF have to return some value */ - lPosEnd = hb_compGenJump( 0 ); - hb_compGenJumpHere( lPosFalse ); - - pExp = pExp->pNext; - if( pExp->exprSize ) - hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - hb_compGenPushNil(); /* IIF have to return some value */ - hb_compGenJumpHere( lPosEnd ); - } - - while( pDel ) - { - pExp = pDel; - pDel = pDel->pNext; - hb_xfree( pExp->exprPCode ); - hb_xfree( pExp ); - } -} - - PFUNCTION GetFuncall( char * szFunctionName ) /* returns a previously called defined function */ { PFUNCTION pFunc = hb_comp_funcalls.pFirst; @@ -2689,135 +2410,99 @@ void hb_compGenPopVar( char * szVarName ) /* generates the pcode to pop a value { int iVar; - if( hb_comp_pAliasId == NULL ) - { - iVar = GetLocalVarPos( szVarName ); - if( iVar ) - hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - else - { - iVar = GetStaticVarPos( szVarName ); - if( iVar ) - { - hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; - } - else - { - VariablePCode( HB_P_POPVARIABLE, szVarName ); - } - } - } + iVar = GetLocalVarPos( szVarName ); + if( iVar ) + hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); else { - if( hb_comp_pAliasId->type == ALIAS_NAME ) + iVar = GetStaticVarPos( szVarName ); + if( iVar ) { - if( hb_comp_pAliasId->alias.szAlias[ 0 ] == 'M' && hb_comp_pAliasId->alias.szAlias[ 1 ] == '\0' ) + hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + VariablePCode( HB_P_POPVARIABLE, szVarName ); + } + } +} + +/* generates the pcode to pop a value from the virtual machine stack onto + * an aliased variable + */ +void hb_compGenPopAliasedVar( char * szVarName, + BOOL bPushAliasValue, + char * szAlias, + long lWorkarea ) +{ + if( bPushAliasValue ) + { + if( szAlias ) + { + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) { /* M->variable */ MemvarPCode( HB_P_POPMEMVAR, szVarName ); } else { - int iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", 4 ); + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); if( iCmp == 0 ) - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", strlen( hb_comp_pAliasId->alias.szAlias ) ); + iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); if( iCmp == 0 ) { /* MEMVAR-> or MEMVA-> or MEMV-> */ MemvarPCode( HB_P_POPMEMVAR, szVarName ); } else { /* field variable */ - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", 4 ); + iCmp = strncmp( szAlias, "FIELD", 4 ); if( iCmp == 0 ) - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", strlen( hb_comp_pAliasId->alias.szAlias ) ); + iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); if( iCmp == 0 ) { /* FIELD-> */ FieldPCode( HB_P_POPFIELD, szVarName ); } else { /* database alias */ - hb_compPushSymbol( yy_strdup( hb_comp_pAliasId->alias.szAlias ), 0 ); + hb_compPushSymbol( yy_strdup( szAlias ), 0 ); FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); } } } } - else if( hb_comp_pAliasId->type == ALIAS_NUMBER ) - { - hb_compGenPushInteger( hb_comp_pAliasId->alias.iAlias ); - FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); - } - else - /* Alias is already placed on stack */ - FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); - } -} - -void hb_compGenPushVar( char * szVarName ) /* generates the pcode to push a variable value to the virtual machine stack */ -{ - int iVar; - - if( hb_comp_pAliasId == NULL ) - { - iVar = GetLocalVarPos( szVarName ); - if( iVar ) - hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); else { - iVar = GetStaticVarPos( szVarName ); - if( iVar ) - { - hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; - } - else - { - VariablePCode( HB_P_PUSHVARIABLE, szVarName ); - } + hb_compGenPushLong( lWorkarea ); + FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); } } + else + /* Alias is already placed on stack */ + FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); +} + +/* generates the pcode to push a nonaliased variable value to the virtual + * machine stack + */ +void hb_compGenPushVar( char * szVarName ) +{ + int iVar; + + iVar = GetLocalVarPos( szVarName ); + if( iVar ) + hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); else { - if( hb_comp_pAliasId->type == ALIAS_NAME ) + iVar = GetStaticVarPos( szVarName ); + if( iVar ) { - if( hb_comp_pAliasId->alias.szAlias[ 0 ] == 'M' && hb_comp_pAliasId->alias.szAlias[ 1 ] == '\0' ) - { /* M->variable */ - MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); - } - else - { - int iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", strlen( hb_comp_pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* MEMVAR-> or MEMVA-> or MEMV-> */ - MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); - } - else - { /* field variable */ - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", strlen( hb_comp_pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* FIELD-> */ - FieldPCode( HB_P_PUSHFIELD, szVarName ); - } - else - { /* database alias */ - hb_compPushSymbol( yy_strdup( hb_comp_pAliasId->alias.szAlias ), 0 ); - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); - } - } - } - } - else if( hb_comp_pAliasId->type == ALIAS_NUMBER ) - { - hb_compGenPushInteger( hb_comp_pAliasId->alias.iAlias ); - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; } else - /* Alias is already placed on stack */ - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + { + VariablePCode( HB_P_PUSHVARIABLE, szVarName ); + } } } @@ -2847,6 +2532,63 @@ void hb_compGenPushVarRef( char * szVarName ) /* generates the pcode to push a v } } + /* generates the pcode to push an aliased variable value to the virtual + * machine stack + */ +void hb_compGenPushAliasedVar( char * szVarName, + BOOL bPushAliasValue, + char * szAlias, + long lWorkarea ) +{ + if( bPushAliasValue ) + { + if( szAlias ) + { + /* myalias->var + * FIELD->var + * MEMVAR->var + */ + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) + { /* M->variable */ + MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { /* field variable */ + iCmp = strncmp( szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* FIELD-> */ + FieldPCode( HB_P_PUSHFIELD, szVarName ); + } + else + { /* database alias */ + hb_compPushSymbol( yy_strdup( szAlias ), 0 ); + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + } + } + } + } + else + { + hb_compGenPushLong( lWorkarea ); + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + } + } + else + /* Alias is already placed on stack */ + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); +} + void hb_compGenPushLogical( int iTrueFalse ) /* pushes a logical value on the virtual machine stack */ { if( iTrueFalse ) diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index f9564ddf7d..1ece43c51a 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -559,6 +559,10 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} +"_fie"|"_fiel"|"_field" { BEGIN FIELD_; + yylval.string = yy_strupr( yy_strdup( yytext ) ); + } + "fiel"|"field" { BEGIN FIELD_; yylval.string = yy_strupr( yy_strdup( yytext ) ); } diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index a37768e7b4..4269a7189f 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -43,12 +43,8 @@ * 4) in some cases incorrect warnings are generated when -w option is used * 5) in some cases GPF occurs when -w option is used, example: * LOCAL nDouble := NumAnd32(RandGetLong() / 65536, 32767) / 997 - * 6) support for expr:expr (QSELF():cVar) syntax. - * see tests/broken/clasname.prg - * 7) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar - * 8) Support this syntax: _FIELD->c->mmezo := mt - * 9) Support this syntax: nPtr := @Hello() - *10) Support for syntax: FOR [ array | object | alias_expr | other ] := value + * 6) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar + * 7) Support this syntax: nPtr := @Hello() */ #include "compiler.h" @@ -281,7 +277,7 @@ ParamList : IDENTIFIER AsType { hb_compAddVar( $1, ' ' ); $$ = 1 * stop compilation if invalid syntax will be used. */ Statement : ExecFlow CrlfStmnt { } - | Expression { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } CrlfStmnt + | Expression CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | BREAK { hb_compGenBreak(); } CrlfStmnt { hb_compGenDoProc( 0 ); } | BREAK { hb_compGenBreak(); } Expression CrlfStmnt { hb_compExprDelete( hb_compExprGenPush( $3 ) ); hb_compGenDoProc( 1 ); } | RETURN CrlfStmnt { @@ -946,13 +942,13 @@ DoCaseBegin : DoCaseStart { } } ; -Cases : CASE Expression Crlf +Cases : CASE Expression Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } - EmptyStats + EmptyStats { $$ = GenElseIf( 0, hb_compGenJump( 0 ) ); hb_compGenJumpHere( $4 ); @@ -965,7 +961,7 @@ Cases : CASE Expression Crlf $$ = hb_compGenJumpFalse( 0 ); Line(); } - EmptyStats + EmptyStats { $$ = GenElseIf( $1, hb_compGenJump( 0 ) ); hb_compGenJumpHere( $5 ); @@ -976,7 +972,7 @@ Cases : CASE Expression Crlf Otherwise : OTHERWISE Crlf { Line(); } EmptyStats ; -DoWhile : WhileBegin Expression Crlf +DoWhile : WhileBegin Expression Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); @@ -1128,9 +1124,9 @@ DoArgList : ',' { hb_compGenPushNil(); hb_compGen | ',' { hb_compGenPushNil(); } DoExpression { $$ = 2; } ; -DoExpression: IDENTIFIER { hb_compGenPushVarRef( $1 ); } - | SimpleExpression { } - | PareExpList { } +DoExpression: IDENTIFIER { hb_compExprDelete( hb_compExprGenPush( hb_compExprNewVarRef( $1 ) ) ); } + | SimpleExpression { hb_compExprDelete( hb_compExprGenPush( $1 ) ); } + | PareExpList { hb_compExprDelete( hb_compExprGenPush( $1 ) ); } ; Crlf : '\n' { ++iLine; }