diff --git a/harbour/ChangeLog b/harbour/ChangeLog index eb29f2d813..c843ca601d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,11 @@ +19990606-15:20 CET Eddie Runia + * source/compiler/harbour.y + - : is now functioning ! + where is +=, -=, *=, /=, %=, ^= + and increment / decrement for : + + tests/working/objasign.prg + test program used + 19990606-13:50 CET Eddie Runia * source/rtl/errorapi.c _ErrNew() stack.Return itself was returned instead of a copy. diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 61603edc56..9ef223ab0e 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -3,11 +3,11 @@ * $Id$ * * Harbour compiler (yacc rules and actions) - * Build 25 + * Build 21 proposal: spring 1999 * Usage: bison -d -v harbour.y You may find Bison at www.harbour.project.org */ -#define BUILD 25 /* current harbour.y build */ +#define BUILD 21 /* current harbour.y build */ #include #include @@ -180,6 +180,7 @@ void Line( void ); /* generates the pcode with the currentl void LineBody( void ); /* generates the pcode with the currently compiled source code line */ void Message( char * szMsgName ); /* sends a message to an object */ void MessageFix( char * szMsgName ); /* fix a generated message to an object */ +void MessageDupl( char * szMsgName ); /* fix a one generated message to an object and duplicate */ void PopId( char * szVarName ); /* generates the pcode to pop a value from the virtual machine stack onto a variable */ void PushDouble( double fNumber, BYTE bDec ); /* Pushes a number on the virtual machine stack */ void PushId( char * szVarName ); /* generates the pcode to push a variable value to the virtual machine stack */ @@ -436,10 +437,10 @@ PATHNAMES *_pIncludePath = NULL; /*the highest precedence*/ %type IDENTIFIER LITERAL FunStart MethStart IdSend ObjectData -%type DOUBLE +%type DOUBLE %type ArgList ElemList ExpList FunCall FunScope IncDec Logical Params ParamList %type INTEGER BlockExpList Argument IfBegin VarId VarList MethParams ObjFunCall -%type MethCall BlockList FieldList +%type MethCall BlockList FieldList %type INTLONG WhileBegin BlockBegin %type IfElseIf Cases @@ -512,7 +513,7 @@ Statement : ExecFlow Crlf {} | IDENTIFIER '=' Expression Crlf { PopId( $1 ); } | VarId ArrayIndex '=' Expression Crlf { GenPCode1( _ARRAYPUT ); GenPCode1( _POP ); } | FunArrayCall '=' Expression Crlf { GenPCode1( _ARRAYPUT ); GenPCode1( _POP ); } - | IdSend IDENTIFIER '=' { Message( SetData( $2 ) ); } Expression Crlf { Function( 1 ); } + | IdSend IDENTIFIER '=' { Message( SetData( $2 ) ); } Expression Crlf { Function( 1 ); } | ObjectData ArrayIndex '=' Expression Crlf { GenPCode1( _ARRAYPUT ); GenPCode1( _POP ); } | ObjectMethod ArrayIndex '=' Expression Crlf { GenPCode1( _ARRAYPUT ); GenPCode1( _POP ); } @@ -640,8 +641,8 @@ VarUnary : IDENTIFIER IncDec %prec POST { PushId( $1 ); Duplicate(); $2 ? I | IncDec VarId ArrayIndex %prec PRE { DupPCode( $2 ); GenPCode1( _ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); } | FunArrayCall IncDec %prec POST { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); $2 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); $2 ? Dec(): Inc(); } | IncDec FunArrayCall %prec PRE { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); } - | ObjectData IncDec %prec POST {} - | IncDec ObjectData %prec PRE {} + | ObjectData IncDec %prec POST { MessageDupl( SetData( $1 ) ); Function( 0 ); $2 ? Inc(): Dec(); Function( 1 ); $2 ? Dec(): Inc(); } + | IncDec ObjectData %prec PRE { MessageDupl( SetData( $2 ) ); Function( 0 ); $1 ? Inc(): Dec(); Function( 1 ); } | ObjectData ArrayIndex IncDec %prec POST { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); $3 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); $3 ? Dec(): Inc(); } | IncDec ObjectData ArrayIndex %prec PRE { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); } | ObjectMethod ArrayIndex IncDec %prec POST { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); $3 ? Inc(): Dec(); GenPCode1( _ARRAYPUT ); $3 ? Dec(): Inc(); } @@ -692,13 +693,13 @@ VarAssign : IDENTIFIER INASSIGN Expression { PopId( $1 ); PushId( $1 ); } | FunArrayCall DIVEQ { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); } Expression { GenPCode1( _DIVIDE ); GenPCode1( _ARRAYPUT ); } | FunArrayCall EXPEQ { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); } Expression { GenPCode1( _POWER ); GenPCode1( _ARRAYPUT ); } | FunArrayCall MODEQ { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); } Expression { GenPCode1( _MODULUS ); GenPCode1( _ARRAYPUT ); } - | ObjectData INASSIGN { MessageFix( SetData( $1 ) ); } Expression { Function( 1 ); } - | ObjectData PLUSEQ Expression {} - | ObjectData MINUSEQ Expression {} - | ObjectData MULTEQ Expression {} - | ObjectData DIVEQ Expression {} - | ObjectData EXPEQ Expression {} - | ObjectData MODEQ Expression {} + | ObjectData INASSIGN { MessageFix ( SetData( $1 ) ); } Expression { Function( 1 ); } + | ObjectData PLUSEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _PLUS ); Function( 1 ); } + | ObjectData MINUSEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _MINUS ); Function( 1 ); } + | ObjectData MULTEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _MULT ); Function( 1 ); } + | ObjectData DIVEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _DIVIDE ); Function( 1 ); } + | ObjectData EXPEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _POWER ); Function( 1 ); } + | ObjectData MODEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPCode1( _MODULUS ); Function( 1 ); } | ObjectData ArrayIndex INASSIGN Expression { GenPCode1( _ARRAYPUT ); } | ObjectData ArrayIndex PLUSEQ { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); } Expression { GenPCode1( _PLUS ); GenPCode1( _ARRAYPUT ); } | ObjectData ArrayIndex MINUSEQ { GenPCode1( _DUPLTWO ); GenPCode1( _ARRAYAT ); } Expression { GenPCode1( _MINUS ); GenPCode1( _ARRAYPUT ); } @@ -2855,6 +2856,32 @@ void Message( char * szMsgName ) /* sends a message to an object */ GenPCode3( _MESSAGE, LOBYTE( wSym ), HIBYTE( wSym ) ); } +void MessageDupl( char * szMsgName ) /* fix a generated message and duplicate to an object */ +{ + WORD wSetSym = GetSymbolPos( szMsgName ); + BYTE bLoGetSym, bHiGetSym; /* get symbol */ + PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ + + if( ! wSetSym ) /* the symbol was not found on the symbol table */ + { + AddSymbol( szMsgName ); + wSetSym = symbols.iCount; + } + GetSymbolOrd( wSetSym - 1 )->cScope |= FS_MESSAGE; + wSetSym -= _iStartProc ? 1: 2; + /* Get previously generated message */ + bLoGetSym = pFunc->pCode[ _lMessageFix + 1]; + bHiGetSym = pFunc->pCode[ _lMessageFix + 2]; + + pFunc->pCode[ _lMessageFix + 1 ] = LOBYTE( wSetSym ); + pFunc->pCode[ _lMessageFix + 2 ] = HIBYTE( wSetSym ); + + pFunc->lPCodePos -= 3; /* Remove unnecessary function call */ + Duplicate(); /* Duplicate object */ + GenPCode3( _MESSAGE, bLoGetSym, bHiGetSym ); + /* Generate new message */ +} + void MessageFix( char * szMsgName ) /* fix a generated message to an object */ { WORD wSym = GetSymbolPos( szMsgName ); diff --git a/harbour/tests/working/objasign.prg b/harbour/tests/working/objasign.prg new file mode 100644 index 0000000000..d5131a0061 --- /dev/null +++ b/harbour/tests/working/objasign.prg @@ -0,0 +1,67 @@ +// +// Object Array syntax test +// + +Function Main + + local o := TNumber():New() + + QOut( "Direct reference : ", o:x ) + + o:x := "I am a data" + QOut( "Assign text : ", o:x ) + + o:x := 4 + QOut( "Assign 4 : ", o:x ) + + QOut( "Post increment : ", o:x++ ) + QOut( "After : ", o:x ) + QOut( "Pre decrement : ", --o:x ) + QOut( "After : ", o:x ) + + o:x += 2 + QOut( "Plus 2 : ", o:x ) + + o:x -= 3 + QOut( "Minus 3 : ", o:x ) + + o:x *= 3 + QOut( "Times 3 : ", o:x ) + + o:x /= 1.5 + QOut( "Divide by 1.5 : ", o:x ) + + o:x %= 4 + QOut( "Modulus 4 : ", o:x ) + + o:x ^= 3 + QOut( "To the power 3 : ", o:x ) + + QOut( "Global stack" ) + HBDebug( __aGlobalStack() ) // Please note a is a reference to aArray ! + QOut( "Statics") + HBDebug( __aStatic() ) +return NIL + +Function TNumber() // Very simple class + + static oNumber + + if oNumber == NIL + oNumber := TClass():New( "TNumber" ) + + oNumber:AddData ( "x" ) + oNumber:AddMethod( "New", @New() ) + oNumber:Create() + endif +return oNumber:Instance() + + +static function New() + + local self := QSelf() + + ::x := 1 +return self + +