Completed parameterised macros

git-svn-id: http://picoc.googlecode.com/svn/trunk@463 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2010-07-11 18:44:07 +00:00
parent 7c754bad48
commit 145a99a7b1
8 changed files with 128 additions and 6 deletions

View file

@ -1099,7 +1099,9 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
ProgramFail(Parser, "identifier not expected here"); ProgramFail(Parser, "identifier not expected here");
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket) if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
{
ExpressionParseFunctionCall(Parser, &StackTop, LexValue->Val->Identifier); ExpressionParseFunctionCall(Parser, &StackTop, LexValue->Val->Identifier);
}
else else
{ {
if (Parser->Mode == RunModeRun) if (Parser->Mode == RunModeRun)
@ -1113,6 +1115,9 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
struct ParseState MacroParser = VariableValue->Val->MacroDef.Body; struct ParseState MacroParser = VariableValue->Val->MacroDef.Body;
struct Value *MacroResult; struct Value *MacroResult;
if (VariableValue->Val->MacroDef.NumParams != 0)
ProgramFail(&MacroParser, "macro arguments missing");
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction) if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
ProgramFail(&MacroParser, "expression expected"); ProgramFail(&MacroParser, "expression expected");
@ -1195,6 +1200,83 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
} }
/* do a parameterised macro call */
void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *MacroName, struct MacroDef *MDef)
{
struct Value *ReturnValue = NULL;
struct Value *Param;
struct Value **ParamArray = NULL;
int ArgCount;
enum LexToken Token;
if (Parser->Mode == RunModeRun)
{
/* create a stack frame for this macro */
ExpressionStackPushValueByType(Parser, StackTop, &FPType); /* largest return type there is */
ReturnValue = (*StackTop)->Val;
HeapPushStackFrame();
ParamArray = HeapAllocStack(sizeof(struct Value *) * MDef->NumParams);
if (ParamArray == NULL)
ProgramFail(Parser, "out of memory");
}
else
ExpressionPushInt(Parser, StackTop, 0);
/* parse arguments */
ArgCount = 0;
do {
if (ExpressionParse(Parser, &Param))
{
if (Parser->Mode == RunModeRun)
{
if (ArgCount < MDef->NumParams)
ParamArray[ArgCount] = Param;
else
ProgramFail(Parser, "too many arguments to %s()", MacroName);
}
ArgCount++;
Token = LexGetToken(Parser, NULL, TRUE);
if (Token != TokenComma && Token != TokenCloseBracket)
ProgramFail(Parser, "comma expected");
}
else
{
/* end of argument list? */
Token = LexGetToken(Parser, NULL, TRUE);
if (!TokenCloseBracket)
ProgramFail(Parser, "bad argument");
}
} while (Token != TokenCloseBracket);
if (Parser->Mode == RunModeRun)
{
/* evaluate the macro */
struct ParseState MacroParser;
int Count;
struct Value *EvalValue;
if (ArgCount < MDef->NumParams)
ProgramFail(Parser, "not enough arguments to '%s'", MacroName);
if (MDef->Body.Pos == NULL)
ProgramFail(Parser, "'%s' is undefined", MacroName);
memcpy((void *)&MacroParser, (void *)&MDef->Body, sizeof(struct ParseState));
VariableStackFrameAdd(Parser, 0);
TopStackFrame->NumParams = ArgCount;
TopStackFrame->ReturnValue = ReturnValue;
for (Count = 0; Count < MDef->NumParams; Count++)
VariableDefine(Parser, MDef->ParamName[Count], ParamArray[Count], NULL, TRUE);
ExpressionParse(&MacroParser, &EvalValue);
ExpressionAssign(Parser, ReturnValue, EvalValue, TRUE, MacroName, 0, FALSE);
VariableStackFramePop(Parser);
HeapPopStackFrame();
}
}
/* do a function call */ /* do a function call */
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName) void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName)
{ {
@ -1209,6 +1291,14 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
{ {
/* get the function definition */ /* get the function definition */
VariableGet(Parser, FuncName, &FuncValue); VariableGet(Parser, FuncName, &FuncValue);
if (FuncValue->Typ->Base == TypeMacro)
{
/* this is actually a macro, not a function */
ExpressionParseMacroCall(Parser, StackTop, FuncName, &FuncValue->Val->MacroDef);
return;
}
if (FuncValue->Typ->Base != TypeFunction) if (FuncValue->Typ->Base != TypeFunction)
ProgramFail(Parser, "%t is not a function - can't call", FuncValue->Typ); ProgramFail(Parser, "%t is not a function - can't call", FuncValue->Typ);

10
lex.c
View file

@ -221,6 +221,9 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
if (Token != TokenNone) if (Token != TokenNone)
return Token; return Token;
if (Lexer->Mode == LexModeHashDefineSpace)
Lexer->Mode = LexModeHashDefineSpaceIdent;
return TokenIdentifier; return TokenIdentifier;
} }
@ -383,7 +386,10 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
#endif #endif
return TokenEndOfLine; return TokenEndOfLine;
} }
else if (Lexer->Mode == LexModeHashDefine) else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace)
Lexer->Mode = LexModeHashDefineSpace;
else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
Lexer->Mode = LexModeNormal; Lexer->Mode = LexModeNormal;
LEXER_INC(Lexer); LEXER_INC(Lexer);
@ -405,7 +411,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
{ {
case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break; case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break;
case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break; case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break;
case '(': if (Lexer->Mode == LexModeHashDefine) { GotToken = TokenOpenMacroBracket; Lexer->Mode = LexModeNormal; } else GotToken = TokenOpenBracket; break; case '(': if (Lexer->Mode == LexModeHashDefineSpaceIdent) GotToken = TokenOpenMacroBracket; else GotToken = TokenOpenBracket; Lexer->Mode = LexModeNormal; break;
case ')': GotToken = TokenCloseBracket; break; case ')': GotToken = TokenCloseBracket; break;
case '=': NEXTIS('=', TokenEqual, TokenAssign); break; case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break; case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break;

View file

@ -242,12 +242,15 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
void ParseMacroDefinition(struct ParseState *Parser) void ParseMacroDefinition(struct ParseState *Parser)
{ {
struct Value *MacroName; struct Value *MacroName;
char *MacroNameStr;
struct Value *ParamName; struct Value *ParamName;
struct Value *MacroValue; struct Value *MacroValue;
if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier) if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
ProgramFail(Parser, "identifier expected"); ProgramFail(Parser, "identifier expected");
MacroNameStr = MacroName->Val->Identifier;
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenMacroBracket) if (LexGetToken(Parser, NULL, FALSE) == TokenOpenMacroBracket)
{ {
/* it's a parameterised macro, read the parameters */ /* it's a parameterised macro, read the parameters */
@ -258,6 +261,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE); MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE);
MacroValue->Val->MacroDef.NumParams = NumParams; MacroValue->Val->MacroDef.NumParams = NumParams;
MacroValue->Val->MacroDef.ParamName = (char **)((char *)MacroValue->Val + sizeof(struct MacroDef));
Token = LexGetToken(Parser, &ParamName, TRUE); Token = LexGetToken(Parser, &ParamName, TRUE);
while (Token == TokenIdentifier) while (Token == TokenIdentifier)
@ -290,8 +295,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
LexToEndOfLine(Parser); LexToEndOfLine(Parser);
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser); MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
if (!TableSet(&GlobalTable, MacroName->Val->Identifier, MacroValue)) if (!TableSet(&GlobalTable, MacroNameStr, MacroValue))
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier); ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
} }
/* copy where we're at in the parsing */ /* copy where we're at in the parsing */

View file

@ -242,7 +242,9 @@ enum LexMode
{ {
LexModeNormal, LexModeNormal,
LexModeHashInclude, LexModeHashInclude,
LexModeHashDefine LexModeHashDefine,
LexModeHashDefineSpace,
LexModeHashDefineSpaceIdent
}; };
struct LexState struct LexState

View file

@ -4,5 +4,5 @@
#define BLOGGS(x) (12*(x)) #define BLOGGS(x) (12*(x))
printf("%d\n", FRED); printf("%d\n", FRED);
//printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3)); printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3));

View file

@ -1 +1,2 @@
12 12
12, 24, 36

8
tests/33_ternary_op.c Normal file
View file

@ -0,0 +1,8 @@
#include <stdio.h>
int Count;
for (Count = 0; Count < 10; Count++)
{
printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3));
}

View file

@ -0,0 +1,10 @@
0
1
4
9
16
15
18
21
24
27