see ChangeLog 1999.05.08-03:02

This commit is contained in:
Ryszard Glab
1999-05-08 02:01:38 +00:00
parent 2df124bece
commit b1bb363c6b
9 changed files with 300 additions and 68 deletions

View File

@@ -1,3 +1,30 @@
Sat May 8 03:02:04 1999 Ryszard Glab <rglab@imid.med.pl>
* source/compiler/harbour.y, source/compiler/harbour.l
-static variables can be accessed in a codeblock even if this
codeblock is a return value (detached static variables)
-Harbour finds now illegal initializations of static variables
(static variables can be initialized using literals only)
-there is no 'redefinition of predefined function' error when the name
of compiled source code is the same as reserved function
-corrected support for /*******/ comments
-Harbour distinguish now 'CASE' variable, 'CASE()' function and
CASE statement (see tests/working/keywords.prg)
* tests/working/keywords.prg
-added many more wild statements to test Harbour compiler
* test/working/statics.prg
-added code to test access of static variables from a codeblock
* source/rtl/extend.c
-added brackets to avoid ambiguous if/else
* source/include/extend.h
* source/rtl/codebloc.c
- added support for static variables in a codeblock
19990507-20:15 EDT David G. Holm <dholm@jsd-llc.com>
* source/compiler/harbour.l
* source/compiler/harbour.y
@@ -37,9 +64,10 @@ Thu May 07 17:00:00 1999 Victor Szel <info@szelvesz.hu>
19990507-07:25 Ryszard Glab <rglab@imid.med.pl>
* source/compiler/harbour.y, source/compiler/harbour.l
-improoved support for BEGIN SEGEUENCE
-added distinction between BEGIN comannd and begin variable
-added distinction between BREAK command and break variable
-improoved support for BEGIN SEGEUENCE
-added distinction between BEGIN command and begin variable
-added distinction between BREAK command and break variable
* tests/working/keywords.prg
-new file to test if we are 100% compatible with Clipper

View File

@@ -64,7 +64,6 @@ typedef struct /* items hold at the virtual machine stack */
void * pBaseArray; /* array base */
} value;
WORD wBase; /* stack frame number of items position for a function call */
PSYMBOL pSymbols; /* codeblocks symbols */
WORD wLine; /* currently processed PRG line number */
WORD wParams; /* number of received parameters for a function call */
} ITEM, * PITEM;
@@ -106,6 +105,7 @@ typedef struct
WORD wDetached; /* holds if pItems table variables values */
PSYMBOL pSymbols; /* codeblocks symbols */
WORD wRefBase; /* stack frame position for referenced local variables */
int iStatBase; /* static base for function where CB was created */
long lCounter; /* numer of references to this codeblock */
} CODEBLOCK, * PCODEBLOCK;

View File

@@ -55,7 +55,15 @@ long lNumber = 0;
#define LOOKUP 0
int _iState = LOOKUP;
//Comment1 "/*"((.*)|(\n))"*/"
void yy_lex_count_lf( void )
{
char * pTmp = yytext;
while( (pTmp = strchr(pTmp, '\n')) )
{
++iLine;
++pTmp;
}
}
%}
@@ -67,7 +75,7 @@ Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+))
String (\"(([^\"]*)|([\!]*))\")|(\'(([^\']*)|([\!]*))\')
PseudoFunc {Identifier}"("+.*")"+
Comment1 "/*"([^\*]|("*"[^\/]))*"*/"
Comment1 "/*"(.*|[\n])"*/"
Comment2 [\/][\/].*
Comment ({Comment1}|{Comment2})
LineCont (;.*\n)
@@ -75,7 +83,7 @@ Separator {SpaceTab}|{Comment}|{LineCont}
%x COMMENT3 DEFINE DEFINE_PARAMS DEFINE_EXPR
%x IFDEF IFNDEF STRING1 STRING2
%x NEXT_ BREAK_
%x NEXT_ BREAK_ CASE_
%%
@@ -96,8 +104,9 @@ Separator {SpaceTab}|{Comment}|{LineCont}
yylval.string[ yyleng - 2 ] = 0; return LITERAL; }
"/*" BEGIN COMMENT3;
<COMMENT3>"*/" BEGIN 0;
<COMMENT3>"*"["*"]*"/" BEGIN 0;
<COMMENT3>[^"*/"\n]* ;
<COMMENT3>"*" ;
<COMMENT3>[\/\"]+ ;
<COMMENT3>\n ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine );
@@ -154,28 +163,64 @@ Separator {SpaceTab}|{Comment}|{LineCont}
}
else
{ /* there is another item in line already */
yylval.string = "BrEaK";
yylval.string = strdup("BrEaK");
return IDENTIFIER;
}
}
<BREAK_>{Separator}*[^_a-zA-Z] { /* there is no identifier after "break" */
yy_lex_count_lf();
BEGIN 0;
yylval.string = ((yytext[ yyleng-1 ] =='(')?"BREAK":"BrEaK");
yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"BREAK":"BrEaK") );
_iState =IDENTIFIER;
unput( yytext[ yyleng-1 ] );
return IDENTIFIER;
}
<BREAK_>{Separator}*. { /* an identifier follows BREAK statement */
yy_lex_count_lf();
BEGIN 0;
unput( yytext[ yyleng-1 ] );
_iState =BREAK;
return BREAK;
}
<BREAK_>. { BEGIN 0; unput( yytext[ yyleng-1 ] ); }
"case" return CASE;
"case" { BEGIN CASE_; }
<CASE_>{Separator}*[\:\=\|\$\%\*\,\/\[\]\)\}] { /* there is an operator after "case" */
yy_lex_count_lf();
BEGIN 0;
yylval.string = strdup( "CASE" );
_iState =IDENTIFIER;
unput( yytext[ yyleng-1 ] );
return IDENTIFIER;
}
<CASE_>{Separator}*("+="|"-=") { /* operators */
yy_lex_count_lf();
BEGIN 0;
yylval.string = strdup( "CASE" );
_iState =IDENTIFIER;
unput( yytext[ yyleng-2 ] );
unput( yytext[ yyleng-1 ] );
return IDENTIFIER;
}
<CASE_>{Separator}*(\n|.) { /* not operator */
yy_lex_count_lf();
BEGIN 0;
if( yytext[ yyleng-1 ] == '\n' )
--iLine;
unput( yytext[ yyleng-1 ] );
if( _iState == LOOKUP )
{ /* it is first item in the line */
_iState =CASE;
return CASE;
}
else
{ /* there is another item in line already */
yylval.string = strdup( "CASE" );
return IDENTIFIER;
}
}
"do" return DO;
"do"{SpaceTab}+"case" return DOCASE;
("do"{SpaceTab}+"while")|"while" return WHILE;
"do"{Separator}+"case" { _iState =DOCASE; return DOCASE; }
("do"{SpaceTab}+"while")|"while" { _iState =WHILE; return WHILE; }
"else" return ELSE;
"elseif" _iState =ELSEIF; return ELSEIF;
"end"/[^(] return END;
@@ -208,18 +253,20 @@ Separator {SpaceTab}|{Comment}|{LineCont}
else
{ /* there is another item in line already */
unput( yytext[ yyleng-1 ] );
yylval.string = "nExT";
yylval.string = strdup( "nExT" );
return IDENTIFIER;
}
}
<NEXT_>{Separator}*[^_a-zA-Z\n\;] { /* there is no identifier after "next" */
<NEXT_>{Separator}*[^_a-zA-Z] { /* there is no identifier after "next" */
yy_lex_count_lf();
BEGIN 0;
yylval.string = ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT");
yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT") );
unput( yytext[ yyleng-1 ] );
_iState =IDENTIFIER;
return IDENTIFIER;
}
<NEXT_>{Separator}*. { /* an identifier follows NEXT statement */
yy_lex_count_lf();
BEGIN 0;
unput( yytext[ yyleng-1 ] );
_iState =NEXT;
@@ -311,7 +358,7 @@ Separator {SpaceTab}|{Comment}|{LineCont}
{String} yylval.string = strdup( yytext + 1 ); yylval.string[ yyleng - 2 ] = 0; return LITERAL;
{LineCont} { ++iLine; }
{LineCont} ++iLine;
{Identifier} {
PDEFINE pDef = FindDef( yytext );

View File

@@ -80,6 +80,8 @@ typedef struct __FUNC /* functions definition support */
*/
#define FUN_STATEMENTS 1 /* Function have at least one executable statement */
#define FUN_USES_STATICS 2 /* Function uses static variables */
#define FUN_PROCEDURE 4 /* This is a procedure that shouldn't return value */
#define FUN_ILLEGAL_INIT 8 /* Attempt to initialize static variable with a function call */
typedef struct
{
@@ -172,7 +174,7 @@ void FixElseIfs( void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */
void FixReturns( void ); /* fixes all last defined function returns jumps offsets */
void Function( BYTE bParams ); /* generates the pcode to execute a Clipper function pushing its result */
PFUNCTION FunctionNew( char *, char ); /* creates and initialises the _FUNC structure */
void FunDef( char * szFunName, char cScope ); /* starts a new Clipper language function definition */
void FunDef( char * szFunName, char cScope, int iType ); /* starts a new Clipper language function definition */
void GenArray( WORD wElements ); /* instructs the virtual machine to build an array and load elemnst from the stack */
void * GenElseIf( void * pFirstElseIf, WORD wOffset ); /* generates a support structure for elseifs pcode fixups */
void GenError( int, char*, char * ); /* generic parsing error management function */
@@ -222,6 +224,7 @@ void CodeBlockEnd( void ); /* end of codeblock creation */
/* Static variables */
void StaticDefStart( void );
void StaticDefEnd( WORD );
void StaticAssign( void ); /* checks if static variable is initialized with function call */
void * OurMalloc( LONG lSize ); /* our malloc with error control */
void * OurRealloc( void * p, LONG lSize ); /* our malloc with error control */
@@ -262,6 +265,7 @@ int iVarScope = 0; /* holds the scope for next variables to be defined
#define ERR_NUMERIC_FORMAT 6
#define ERR_STRING_TERMINATOR 7
#define ERR_FUNC_RESERVED 8
#define ERR_ILLEGAL_INIT 9
/* Table with parse errors */
char * _szErrors[] = { "Statement not allowed outside of procedure or function",
@@ -271,7 +275,8 @@ char * _szErrors[] = { "Statement not allowed outside of procedure or function",
"Outer codeblock variable is out of reach: \'%s\'",
"Invalid numeric format '.'",
"Unterminated string: \'%s\'",
"Redefinition of predefined function %s: \'%s\'"
"Redefinition of predefined function %s: \'%s\'",
"Illegal initializer: \'%s\'"
};
/* Table with reserved functions names
@@ -468,8 +473,8 @@ ExtList : IDENTIFIER { AddExtern( $1 ); }
| ExtList ',' IDENTIFIER { AddExtern( $3 ); }
;
Function : FunScope FUNCTION IDENTIFIER { FunDef( $3, $1 ); } Params Crlf { SetFrame(); }
| FunScope PROCEDURE IDENTIFIER { FunDef( $3, $1 ); } Params Crlf { SetFrame(); }
Function : FunScope FUNCTION IDENTIFIER { FunDef( $3, $1, 0 ); } Params Crlf { SetFrame(); }
| FunScope PROCEDURE IDENTIFIER { FunDef( $3, $1, FUN_PROCEDURE ); } Params Crlf { SetFrame(); }
;
FunScope : { $$ = FS_PUBLIC; }
@@ -523,14 +528,14 @@ FunCall : FunStart ')' { $$ = 0; }
| FunStart ArgList ')' { $$ = $2; }
;
FunStart : IDENTIFIER '(' { PushSymbol( $1, 1 ); PushNil(); $$ = $1; }
FunStart : IDENTIFIER '(' { StaticAssign(); PushSymbol( $1, 1 ); PushNil(); $$ = $1; }
;
MethCall : MethStart ')' { $$ = 0; }
| MethStart ArgList ')' { $$ = $2; }
;
MethStart : IDENTIFIER '(' { Message( $1 ); $$ = $1; }
MethStart : IDENTIFIER '(' { StaticAssign(); Message( $1 ); $$ = $1; }
;
ArgList : ',' { PushNil(); PushNil(); $$ = 2; }
@@ -1127,7 +1132,7 @@ int harbour_main( int argc, char * argv[] )
if( Include( szFileName ) )
{
FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC );
FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC, FUN_PROCEDURE );
yyparse();
FixReturns(); /* fix all previous function returns offsets */
fclose( yyin );
@@ -1397,7 +1402,14 @@ void AddVar( char * szVarName )
* defined is stored in pOwner member.
*/
if( iVarScope == VS_STATIC )
{
pFunc =pFunc->pOwner;
/* Check if an illegal action was invoked during a static variable
* value initialization
*/
if( _pInitFunc->bFlags & FUN_ILLEGAL_INIT )
GenError( ERR_ILLEGAL_INIT, szVarName, pFunc->szName );
}
/* Check if a declaration of duplicated variable name is requested */
if( pFunc->szName )
@@ -1583,7 +1595,13 @@ PFUNCTION FunctionNew( char *szName, char cScope )
return pFunc;
}
void FunDef( char * szFunName, char cScope ) /* stores a Clipper defined function */
/*
* Stores a Clipper defined function/procedure
* szFunName - name of a function
* cScope - scope of a function
* iType - FUN_PROCEDURE if a procedure or 0
*/
void FunDef( char * szFunName, char cScope, int iType )
{
PCOMSYMBOL pSym;
PFUNCTION pFunc;
@@ -1620,6 +1638,7 @@ void FunDef( char * szFunName, char cScope ) /* stores a Clipper defined functi
pSym->cScope |= cScope; /* we may have a non public function and a object message */
pFunc =FunctionNew( szFunName, cScope );
pFunc->bFlags |= iType;
if( functions.iCount == 0 )
{
@@ -2677,6 +2696,14 @@ void PushId( char * szVarName ) /* generates the pcode to push a variable value
{
WORD wVar;
if( iVarScope == VS_STATIC )
{
/* Reffering to any variable is not allowed during initialization
* of static variable
*/
_pInitFunc->bFlags |= FUN_ILLEGAL_INIT;
}
if( ( wVar = GetLocalVarPos( szVarName ) ) )
GenPCode3( _PUSHLOCAL, LOBYTE( wVar ), HIBYTE( wVar ) );
@@ -2698,6 +2725,14 @@ void PushIdByRef( char * szVarName ) /* generates the pcode to push a variable b
{
WORD wVar;
if( iVarScope == VS_STATIC )
{
/* Reffering to any variable is not allowed during initialization
* of static variable
*/
_pInitFunc->bFlags |= FUN_ILLEGAL_INIT;
}
if( ( wVar = GetLocalVarPos( szVarName ) ) )
GenPCode3( _PUSHLOCALREF, LOBYTE( wVar ), HIBYTE( wVar ) );
@@ -3110,7 +3145,7 @@ void StaticDefStart( void )
{
_pInitFunc =FunctionNew( "_INITSTATICS", FS_INIT );
_pInitFunc->pOwner =functions.pLast;
_pInitFunc->bFlags =FUN_USES_STATICS;
_pInitFunc->bFlags =FUN_USES_STATICS | FUN_PROCEDURE;
functions.pLast =_pInitFunc;
PushInteger( 1 ); /* the number of static variables is unknown now */
GenPCode3( _STATICS, 0, 0 );
@@ -3133,6 +3168,18 @@ void StaticDefEnd( WORD wCount )
functions.pLast =_pInitFunc->pOwner;
_pInitFunc->pOwner =NULL;
_wStatics += wCount;
iVarScope =0;
}
/*
* This function checks if we are initializing a static variable.
* It should be called only in case when the parser have recognized any
* function or method invocation.
*/
void StaticAssign( void )
{
if( iVarScope == VS_STATIC )
_pInitFunc->bFlags |= FUN_ILLEGAL_INIT;
}
void * OurMalloc( LONG lSize )

View File

@@ -23,7 +23,8 @@ extern STACK stack;
* +2 bytes -> table of referenced local variables
* +2 + 2 *(number of referenced variables) -> codeblock pcode
*/
PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols )
PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols,
int iStaticsBase, WORD wStackBase )
{
PCODEBLOCK pCBlock;
WORD wVars;
@@ -61,18 +62,26 @@ PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols )
/* the codeblock initally contains references to local variables
*/
pCBlock->wDetached =FALSE;
/* since the only allowed operation on a codeblock is evaluating it then
* there is no need to duplicate its pcode -just store the poiter to it
/*
* pcode is stored in static segment now.
* The only allowed operation on a codeblock is evaluating it then
* there is no need to duplicate its pcode -just store the pointer to it
*/
pCBlock->pCode = (BYTE *) _xgrab( wSize );
memcpy( pCBlock->pCode, pBuffer, wSize );
pCBlock->pCode = pBuffer;
pCBlock->pSymbols =pSymbols;
pCBlock->wDetached =FALSE;
pCBlock->lCounter =1;
pCBlock->iStatBase =iStaticsBase;
/*
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
* at the time of codeblock evaluation.
*/
pCBlock->wRefBase =wStackBase;
#ifdef CODEBLOCKDEBUG
printf( "codeblock created (%li)\n", pCBlock->lCounter );
printf( "codeblock created (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
return pCBlock;
}
@@ -82,7 +91,7 @@ PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols )
void CodeblockDelete( PCODEBLOCK pCBlock )
{
#ifdef CODEBLOCKDEBUG
printf( "delete a codeblock (%li)\n", pCBlock->lCounter );
printf( "delete a codeblock (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
if( --pCBlock->lCounter == 0 )
{
@@ -92,14 +101,11 @@ void CodeblockDelete( PCODEBLOCK pCBlock )
*/
while( w < pCBlock->wLocals )
ItemRelease( &pCBlock->pItems[ w++ ] );
/* free space allocated for a codeblock pcodes
*/
_xfree( pCBlock->pCode );
/* free space allocated for a CODEBLOCK structure
*/
_xfree( pCBlock );
#ifdef CODEBLOCKDEBUG
printf( "codeblock deleted (%li)\n", pCBlock->lCounter );
printf( "codeblock deleted (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
}
}
@@ -132,7 +138,7 @@ void CodeblockDetach( PCODEBLOCK pCBlock )
pCBlock->wDetached =TRUE;
}
#ifdef CODEBLOCKDEBUG
printf( "codeblock detached(%li)\n", pCBlock->lCounter );
printf( "codeblock detached(%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
}
@@ -140,10 +146,13 @@ void CodeblockDetach( PCODEBLOCK pCBlock )
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
*/
void CodeblockEvaluate( PCODEBLOCK pCBlock, WORD wStackBase )
void CodeblockEvaluate( PCODEBLOCK pCBlock )
{
pCBlock->wRefBase =wStackBase;
int iStatics = stack.iStatics;
stack.iStatics = pCBlock->iStatBase;
VirtualMachine( pCBlock->pCode, pCBlock->pSymbols );
stack.iStatics = iStatics;
}
/* Get local variable referenced in a codeblock
@@ -175,6 +184,6 @@ void CodeblockCopy( PITEM pDest, PITEM pSource )
pDest->value.pCodeblock =pSource->value.pCodeblock;
((PCODEBLOCK) pDest->value.pCodeblock)->lCounter++;
#ifdef CODEBLOCKDEBUG
printf( "copy a codeblock (%li)\n", ((PCODEBLOCK) pDest->value.pCodeblock)->lCounter);
printf( "copy a codeblock (%li) %lx\n", ((PCODEBLOCK) pDest->value.pCodeblock)->lCounter, pDest->value.pCodeblock);
#endif
}

View File

@@ -44,11 +44,12 @@ char * _parc( WORD wParam, ... )
pItem = stack.pBase + 1 + wParam;
if( IS_ARRAY( pItem ) )
{
if( wArrayIndex )
return ArrayGetString( pItem, wArrayIndex );
else
return "";
}
else if( IS_STRING( pItem ) )
return pItem->value.szText;
@@ -73,11 +74,12 @@ ULONG _parclen( WORD wParam, ... )
pItem = stack.pBase + 1 + wParam;
if( IS_ARRAY( pItem ) )
{
if( wArrayIndex )
return ArrayGetStringLen( pItem, wArrayIndex );
else
return 0;
}
else if( IS_STRING( pItem ) )
return pItem->wLength;

View File

@@ -112,10 +112,10 @@ void StackPush( void ); /* pushes an item on to the stack */
void StackInit( void ); /* initializes the stack */
void StackShow( void ); /* show the types of the items on the stack for HBDEBUGging purposes */
PCODEBLOCK CodeblockNew( BYTE *, WORD, PSYMBOL );
PCODEBLOCK CodeblockNew( BYTE *, WORD, PSYMBOL, int, WORD );
void CodeblockDelete( PCODEBLOCK );
PITEM CodeblockGetVar( PITEM, SHORT );
void CodeblockEvaluate( PCODEBLOCK, WORD );
void CodeblockEvaluate( PCODEBLOCK );
void CodeblockCopy( PITEM, PITEM );
void CodeblockDetach( PCODEBLOCK );
@@ -608,7 +608,7 @@ void Do( WORD wParams )
WORD wItemIndex = pItem - stack.pItems;
PITEM pSelf = stack.pPos - wParams - 1;
HARBOURFUNC pFunc;
WORD iStatics = stack.iStatics; /* Return iStatics position */
int iStatics = stack.iStatics; /* Return iStatics position */
if( ! IS_SYMBOL( pItem ) )
{
@@ -683,7 +683,7 @@ HARBOUR DoBlock( void )
*/
stack.pBase->wLine =pBlock->wLine;
CodeblockEvaluate( (PCODEBLOCK)pBlock->value.pCodeblock, pBlock->wBase );
CodeblockEvaluate( (PCODEBLOCK)pBlock->value.pCodeblock );
/* restore stack pointers */
stack.pBase = stack.pItems + wStackBase;
@@ -1526,7 +1526,8 @@ void PushBlock( BYTE * pCode, WORD wSize, WORD wParam, PSYMBOL pSymbols )
{
ItemRelease( stack.pPos );
stack.pPos->wType = IT_BLOCK;
stack.pPos->value.pCodeblock = (BYTE *)CodeblockNew( pCode, wSize, pSymbols );
stack.pPos->value.pCodeblock = (BYTE *)CodeblockNew( pCode, wSize, pSymbols,
stack.iStatics, stack.pBase - stack.pItems );
/* store the stack base of function where the codeblock was defined */
stack.pPos->wBase = stack.pBase - stack.pItems;
/* store the number of expected parameters */

View File

@@ -1,19 +1,29 @@
/*
* $Id$
*/
//DO NOT RUN THIS PROGRAM - ITS PURPOSE IS THE SYNTAX CHECK ONLY!
STATIC nExt, bEgin, bReak
STATIC nExt, bEgin, bReak, cAse
Function Main()
NEXT(nExt)
BEGIN( bEgin +';' + ; //////
";" ; /* ;;;;;just trying to be smart;;;;;;; */
//just to prevent any disaster if someone will want to run it
IF( .T. )
RETURN nil
ENDIF
NEXT(nExt) //in Clipper: NEXT does not match FOR
BEGIN( bEgin +';' + ;; //////Clipper doesn't like more then one ';'
";" ; /* ;;;;;Clipper doesn't like this comment after ';' ;;;;;;; */
)
BREAK_(bReak)
// CASE(case) //it is not possible to call case() in this context
case :=CASE( CASE ) //this is valid
RETURN nil
/*================================================================
************************************************ Checking for NEXT
* * * * * ** Checking for NEXT
*/
FUNCTION NeXT( next_next/*next next*/ )
Local nExt, nExt7, nExtNEXT
@@ -23,15 +33,24 @@ Local nExt, nExt7, nExtNEXT
OutStd( nExT ) // Actually this needs to use str()
Next /*next*/ nExt //next
//NEXT
FOR nExt = 1 TO nExt
QOut( nExt )
NEXT
FOR nExt :=1 TO 10
QOut( nExt )
NEXT ; ////////// ;
NEXT
nExt := 10 //next
nExt++ /*n_ext*/ //---
nExt++ /*in Clipper: NEXT does not match FOR*/
--nExt /*next*/
nExt7 :=7
nExtNEXT := nExt //next
nExt[ 1 ] :=nExt //in Clipper: NEXT does not match FOR
nExt[ nExt ] := NEXT( nExt[nExt+nExt] * nExt *(nExt+nExt*5) )
IF( nExt > nExt+4 )
@@ -48,11 +67,10 @@ RETURN( nExt * /*next*/ nExt )
* Checking for BEGIN
*/
FUNCTION BEGIN( BEGIN_BEGIN )
//LOCAL bEgin, xbEgin , bEginBEGIN , bEgin0, xbEginBEGIN:=100
LOCAL bEgin
LOCAL xbEgin
LOCAL bEginBEGIN
LOCAL bEgin0, /* BEGIN OF BEGIN */ ; /* begin */
LOCAL bEgin0, /* BEGIN OF BEGIN */ ; /* in Clipper: Incomplete statement */
bEgin1
LOCAL xbEginBEGIN := 100
@@ -91,12 +109,28 @@ LOCAL bReak:=0
IF( bReak = 0 )
Break /*break*/ ( nil )
BREAK /* break to beggining */
Break() //this line is not valid in Clipper: syntax error: ')'
Break() //in Clipper: syntax error: ')'
ENDIF
Break /* break in break */ ;;;
; /////////////
()
Break /**** BREAK AGAIN ****/; ;;;;;
; //////////////////////////////////////////////////
; //What
; //the
; //comment
; //like
; //it
; //is
; //doing
; //in
; //this
; //place?
; //Do
; //you
; //use
; //it
; //often?
;///////////////////////////////////////////////////
() //in Clipper: incomplete statement or unbalanced delimiters
begin sequence
FOR bReak:=1 To 10
@@ -109,4 +143,51 @@ recover USING bReak
end
BREAK
RETURN bReak[ bReak ]
RETURN bReak[ bReak ] //in Clipper: syntax error ' BREAK '
/*====================================================================
* Test for CASE/DO CASE
*/
FUNCTION CASE( case_ )
LOCAL case
FOR case:=1 TO 15
QUOT( case )
QOUT( case * ; ////
case )
NEXT case
case[ case ] :=case //in Clipper: Case is not immediatelly within DO CASE
case[ 2 ] :=2 //in Clipper: the same as above - Harbour compiles both
case =case + case - case
case :={|case| case( case )}
case :={|| case }
DO /* case */ CASE
CASE 1
case =case ** case
CASE 2+case
case =case +1
CASE case++
// case-- //sorry -Clipper also doesn't compile this line
// case++ //sorry -Clipper also doesn't compile this line
CASE ++case
++case
CASE ;
case( case )
CASE CASE
CASE !CASE
CASE -CASE
CASE +CASE
/*
*
*
*/
CASE( CASE )
case =case != case
CASE( CASE ) //new CASE or function call? :)
OTHERWISE
case *=case
ENDCASE
RETURN case

View File

@@ -3,9 +3,9 @@
static z := "First"
function Main()
LOCAL i
LOCAL i, cb
static a := "Hello", b := { 1, 3 }
static a := "Hello", b := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
QOut( a )
QOut( b[ 2 ] )
@@ -17,6 +17,11 @@ LOCAL i
FOR i:=1 TO 10
NumStat()
NEXT
cb :=DetachVar( 10 )
FOR i:=1 To 10
QOut( EVAL( cb, b[ i ] ) )
NEXT
return nil
@@ -32,8 +37,20 @@ FUNCTION THREE( p )
QOut( p )
RETURN p
PROCEDURE NumStat()
STATIC n:=0
PROCEDURE NumStat(a)
STATIC n:=1
LOCAL cb
//STATIC m:=n //uncomment it to see an error
//STATIC m:=Time() //uncomment it to see an error
cb :={|x| z +STR(x)}
QOut( ++n )
QOut( z )
RETURN
QOut( EVAL( cb,n ) )
RETURN
FUNCTION DetachVar( xLocal )
STATIC xStatic:=100
RETURN( {|x| ++xStatic, x+xStatic+xLocal} )