Skip to content

Commit

Permalink
Introduce #@ pragmas
Browse files Browse the repository at this point in the history
This is an experimental syntax extension to add arbitrary annotations
into statement sequences.

This, together with the syntaxtree module will enable users to process
GAP source without writing their own ad-hoc parsers.
  • Loading branch information
markuspf committed Oct 26, 2017
1 parent 4251627 commit 07f7fb9
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 30 deletions.
11 changes: 11 additions & 0 deletions src/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,17 @@ void CodeFuncExprEnd (

}

void CodePragma(Obj content)
{
Stat pragma;

pragma = NewStat( T_PRAGMA, SIZEBAG_STRINGLEN(GET_LEN_STRING(content)) );
memcpy( (void *)ADDR_STAT(pragma), CONST_ADDR_OBJ(content),
SIZEBAG_STRINGLEN(GET_LEN_STRING(content)) );

PushStat( pragma );
}


/****************************************************************************
**
Expand Down
4 changes: 4 additions & 0 deletions src/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ enum STAT_TNUMS {
T_ASSERT_2ARGS,
T_ASSERT_3ARGS,

T_PRAGMA,

END_ENUM_RANGE(LAST_STAT_TNUM),
};

Expand Down Expand Up @@ -1401,6 +1403,8 @@ extern void CodeAssertEnd3Args ( void );
/* CodeContinue() . . . . . . . . . . . . . code continue-statement */
extern void CodeContinue ( void );

extern void CodePragma(Obj pragma);

/****************************************************************************
**
*V FilenameCache . . . . . . . . . . . . . . . . . . list of filenames
Expand Down
10 changes: 10 additions & 0 deletions src/intrprtr.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,16 @@ ExecStatus IntrEnd (
}


/* Interpret a pragma, that is, if we're coding, code it, otherwise
ignore it */
void IntrPragma(Obj pragma)
{
/* ignore or code */
if ( STATE(IntrReturning) > 0 ) { return; }
if ( STATE(IntrIgnoring) > 0 ) { return; }
if ( STATE(IntrCoding) > 0 ) { CodePragma(pragma); return; }
}

/****************************************************************************
**
*F IntrFuncCallBegin() . . . . . . . . . . . interpret function call, begin
Expand Down
2 changes: 2 additions & 0 deletions src/intrprtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,8 @@ extern void IntrSaveWSEnd ( void );
*/
extern void IntrContinue ( void );

extern void IntrPragma(Obj pragma);

/****************************************************************************
*F PushVoidObj() . . . . . . . . . . . . . . push void value onto the stack
*/
Expand Down
80 changes: 55 additions & 25 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,18 @@ void ReadReturn (
}
}

void ReadPragma(TypSymbolSet follow)
{
Obj pragma;
UInt len;

C_NEW_STRING( pragma, STATE(ValueLen), (void *)STATE(Value) );
len = STATE(ValueLen);
SET_LEN_STRING(pragma, len);
*(CHARS_STRING(pragma) + len) = 0;
Match(S_PRAGMA, "pragma", follow);
IntrPragma( pragma );
}

/****************************************************************************
**
Expand Down Expand Up @@ -2657,37 +2669,55 @@ void ReadQUIT (
** | 'atomic' <QualifiedExpression> { ',' <QualifiedExpression> } 'do' <Statements> 'od' ';'
** | ';'
*/
UInt ReadStats (
TypSymbolSet follow )
UInt ReadStats(TypSymbolSet follow)
{
UInt nr; /* number of statements */
UInt nr; /* number of statements */

/* read the statements */
nr = 0;
while ( IS_IN( STATE(Symbol), STATBEGIN|S_SEMICOLON ) ) {

/* read a statement */
if ( STATE(Symbol) == S_IDENT ) ReadCallVarAss(follow,'s');
else if ( STATE(Symbol) == S_UNBIND ) ReadUnbind( follow );
else if ( STATE(Symbol) == S_INFO ) ReadInfo( follow );
else if ( STATE(Symbol) == S_ASSERT ) ReadAssert( follow );
else if ( STATE(Symbol) == S_IF ) ReadIf( follow );
else if ( STATE(Symbol) == S_FOR ) ReadFor( follow );
else if ( STATE(Symbol) == S_WHILE ) ReadWhile( follow );
else if ( STATE(Symbol) == S_REPEAT ) ReadRepeat( follow );
else if ( STATE(Symbol) == S_BREAK ) ReadBreak( follow );
else if ( STATE(Symbol) == S_CONTINUE) ReadContinue( follow );
else if ( STATE(Symbol) == S_RETURN ) ReadReturn( follow );
else if ( STATE(Symbol) == S_TRYNEXT) ReadTryNext( follow );
else if ( STATE(Symbol) == S_QUIT ) ReadQuit( follow );
else if ( STATE(Symbol) == S_ATOMIC ) ReadAtomic( follow );
else ReadEmpty( follow );
nr++;
Match( S_SEMICOLON, ";", follow );
while (IS_IN(STATE(Symbol), STATBEGIN | S_SEMICOLON)) {

if (STATE(Symbol) == S_PRAGMA)
ReadPragma(follow);
else {
/* read a statement */
if (STATE(Symbol) == S_IDENT)
ReadCallVarAss(follow, 's');
else if (STATE(Symbol) == S_UNBIND)
ReadUnbind(follow);
else if (STATE(Symbol) == S_INFO)
ReadInfo(follow);
else if (STATE(Symbol) == S_ASSERT)
ReadAssert(follow);
else if (STATE(Symbol) == S_IF)
ReadIf(follow);
else if (STATE(Symbol) == S_FOR)
ReadFor(follow);
else if (STATE(Symbol) == S_WHILE)
ReadWhile(follow);
else if (STATE(Symbol) == S_REPEAT)
ReadRepeat(follow);
else if (STATE(Symbol) == S_BREAK)
ReadBreak(follow);
else if (STATE(Symbol) == S_CONTINUE)
ReadContinue(follow);
else if (STATE(Symbol) == S_RETURN)
ReadReturn(follow);
else if (STATE(Symbol) == S_TRYNEXT)
ReadTryNext(follow);
else if (STATE(Symbol) == S_QUIT)
ReadQuit(follow);
else if (STATE(Symbol) == S_ATOMIC)
ReadAtomic(follow);
else if (STATE(Symbol) == S_PRAGMA)
ReadPragma(follow);
else
ReadEmpty(follow);
Match(S_SEMICOLON, ";", follow);
}
nr++;
}

/* return the number of statements */
/* return the number of statements */
return nr;
}

Expand Down
32 changes: 27 additions & 5 deletions src/scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,22 @@ void GetChar ( void )
}
}

void GetPragma(void)
{
Int i = 0;

/* Skip @ */
GET_CHAR();
while (*STATE(In) != '\n' && *STATE(In) != '\r' &&
*STATE(In) != '\377') {
STATE(Value)[i] = *STATE(In);
i++;
GET_CHAR();
}
STATE(Value)[i] = '\0';
STATE(ValueLen) = i;
}

/****************************************************************************
**
*F GetSymbol() . . . . . . . . . . . . . . . . . get the next symbol, local
Expand Down Expand Up @@ -2151,20 +2167,26 @@ void GetSymbol ( void )
GET_CHAR();
}

/* skip over <spaces>, <tabs>, <newlines> and comments */
/* skip over <spaces>, <tabs>, and <newlines> */
while (*STATE(In) == ' ' || *STATE(In) == '\t' || *STATE(In) == '\n' ||
*STATE(In) == '\r' || *STATE(In) == '\f' || *STATE(In) == '#') {
if (*STATE(In) == '#') {
while (*STATE(In) != '\n' && *STATE(In) != '\r' &&
*STATE(In) != '\377')
GET_CHAR();
GET_CHAR();
if (*STATE(In) == '@') {
STATE(Symbol) = S_PRAGMA;
GetPragma();
return;
} else {
while (*STATE(In) != '\n' && *STATE(In) != '\r' &&
*STATE(In) != '\377')
GET_CHAR();
}
}
GET_CHAR();
}

/* switch according to the character */
switch (*STATE(In)) {

case '.':
STATE(Symbol) = S_DOT;
GET_CHAR();
Expand Down
12 changes: 12 additions & 0 deletions src/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,17 @@ void PrintAtomic (
Pr( "%4<\nod;", 0L, 0L );
}

void PrintPragma(Stat stat)
{
Char *pragma;

/* TODO: super ugly */
pragma = (Char *)((UInt *)(&ADDR_STAT(stat)[1]));

Pr("#@", 0L, 0L);
Pr("%s", (Int)(pragma), 0L);
}


/****************************************************************************
**
Expand Down Expand Up @@ -2309,6 +2320,7 @@ static Int InitKernel (
InstallPrintStatFunc( T_RETURN_VOID , PrintReturnVoid);
InstallPrintStatFunc( T_EMPTY , PrintEmpty);
InstallPrintStatFunc( T_ATOMIC , PrintAtomic);
InstallPrintStatFunc( T_PRAGMA , PrintPragma);

for ( i = 0; i < ARRAY_SIZE(ExecStatFuncs); i++ )
IntrExecStatFuncs[i] = ExecIntrStat;
Expand Down

0 comments on commit 07f7fb9

Please sign in to comment.