More work on expressions. Trying to get variable lookups to work in the new system.
git-svn-id: http://picoc.googlecode.com/svn/trunk@217 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
61174fb115
commit
74673d965a
190
expression.c
190
expression.c
|
@ -14,10 +14,10 @@
|
||||||
#define BRACKET_PRECEDENCE 20
|
#define BRACKET_PRECEDENCE 20
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
/* local prototypes */
|
/* local prototypes */
|
||||||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName);
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName);
|
||||||
|
|
||||||
#if 1
|
|
||||||
/* parse a single value */
|
/* parse a single value */
|
||||||
int ExpressionParseValue(struct ParseState *Parser, struct Value **Result)
|
int ExpressionParseValue(struct ParseState *Parser, struct Value **Result)
|
||||||
{
|
{
|
||||||
|
@ -418,8 +418,97 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do a function call */
|
||||||
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName)
|
||||||
|
{
|
||||||
|
struct Value *FuncValue;
|
||||||
|
struct Value *Param;
|
||||||
|
struct Value **ParamArray = NULL;
|
||||||
|
int ArgCount;
|
||||||
|
enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
||||||
|
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{ /* get the function definition */
|
||||||
|
VariableGet(Parser, FuncName, &FuncValue);
|
||||||
|
if (FuncValue->Typ->Base != TypeFunction)
|
||||||
|
ProgramFail(Parser, "not a function - can't call");
|
||||||
|
|
||||||
|
*Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, FALSE, NULL);
|
||||||
|
HeapPushStackFrame();
|
||||||
|
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
||||||
|
if (ParamArray == NULL)
|
||||||
|
ProgramFail(Parser, "out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse arguments */
|
||||||
|
ArgCount = 0;
|
||||||
|
do {
|
||||||
|
if (ExpressionParse(Parser, &Param))
|
||||||
|
{
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{
|
||||||
|
if (ArgCount >= FuncValue->Val->FuncDef.NumParams)
|
||||||
|
{
|
||||||
|
if (!FuncValue->Val->FuncDef.VarArgs)
|
||||||
|
ProgramFail(Parser, "too many arguments to %s()", FuncName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FuncValue->Val->FuncDef.ParamType[ArgCount] != Param->Typ)
|
||||||
|
ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount+1, FuncName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||||
|
ParamArray[ArgCount] = Param;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{ /* run the function */
|
||||||
|
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||||
|
ProgramFail(Parser, "not enough arguments to '%s'", FuncName);
|
||||||
|
|
||||||
|
if (FuncValue->Val->FuncDef.Intrinsic == NULL)
|
||||||
|
{ /* run a user-defined function */
|
||||||
|
struct ParseState FuncParser = FuncValue->Val->FuncDef.Body;
|
||||||
|
int Count;
|
||||||
|
|
||||||
|
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
||||||
|
TopStackFrame->NumParams = ArgCount;
|
||||||
|
TopStackFrame->ReturnValue = *Result;
|
||||||
|
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
||||||
|
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]);
|
||||||
|
|
||||||
|
if (!ParseStatement(&FuncParser))
|
||||||
|
ProgramFail(&FuncParser, "function body expected");
|
||||||
|
|
||||||
|
if (FuncValue->Val->FuncDef.ReturnType != (*Result)->Typ)
|
||||||
|
ProgramFail(&FuncParser, "bad type of return value");
|
||||||
|
|
||||||
|
VariableStackFramePop(Parser);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FuncValue->Val->FuncDef.Intrinsic(Parser, *Result, ParamArray, ArgCount);
|
||||||
|
|
||||||
|
HeapPopStackFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
enum OperatorOrder
|
enum OperatorOrder
|
||||||
{
|
{
|
||||||
OrderNone,
|
OrderNone,
|
||||||
|
@ -470,6 +559,8 @@ static struct OpPrecedence OperatorPrecedence[] =
|
||||||
/* TokenOpenBracket, */ { 15, 0, 0 }, /* TokenCloseBracket, */ { 0, 15, 0 }
|
/* TokenOpenBracket, */ { 15, 0, 0 }, /* TokenCloseBracket, */ { 0, 15, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName);
|
||||||
|
|
||||||
|
|
||||||
/* push a node on to the expression stack */
|
/* push a node on to the expression stack */
|
||||||
void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *ValueLoc)
|
void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *ValueLoc)
|
||||||
|
@ -480,6 +571,13 @@ void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionSt
|
||||||
*StackTop = StackNode;
|
*StackTop = StackNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* push a blank value on to the expression stack by type */
|
||||||
|
void ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType)
|
||||||
|
{
|
||||||
|
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL);
|
||||||
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
||||||
|
}
|
||||||
|
|
||||||
/* push a value on to the expression stack */
|
/* push a value on to the expression stack */
|
||||||
void ExpressionStackPushValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue)
|
void ExpressionStackPushValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue)
|
||||||
{
|
{
|
||||||
|
@ -496,7 +594,7 @@ void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **Stack
|
||||||
|
|
||||||
void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackTop, double FPValue)
|
void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackTop, double FPValue)
|
||||||
{
|
{
|
||||||
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL);
|
||||||
ValueLoc->Val->FP = FPValue;
|
ValueLoc->Val->FP = FPValue;
|
||||||
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
||||||
}
|
}
|
||||||
|
@ -895,6 +993,38 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
ProgramFail(Parser, "operator not expected here");
|
ProgramFail(Parser, "operator not expected here");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (Token == TokenIdentifier)
|
||||||
|
{ /* it's a variable, function or a macro */
|
||||||
|
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
|
||||||
|
ExpressionParseFunctionCall(Parser, &StackTop, LexValue->Val->Identifier);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{
|
||||||
|
struct Value *VariableValue = NULL;
|
||||||
|
|
||||||
|
VariableGet(Parser, LexValue->Val->Identifier, &VariableValue);
|
||||||
|
if (VariableValue->Typ->Base == TypeMacro)
|
||||||
|
{
|
||||||
|
ProgramFail(Parser, "XXX macros unimplemented");
|
||||||
|
#if 0
|
||||||
|
struct ParseState MacroParser = VariableValue->Val->Parser;
|
||||||
|
|
||||||
|
if (!ExpressionParse(&MacroParser, Result) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
||||||
|
ProgramFail(&MacroParser, "expression expected");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (VariableValue->Typ == TypeVoid)
|
||||||
|
ProgramFail(Parser, "a void value isn't much use here");
|
||||||
|
else
|
||||||
|
{ /* it's a value variable */
|
||||||
|
ExpressionStackPushValue(Parser, &StackTop, VariableValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* push a dummy value */
|
||||||
|
ExpressionStackPushValueByType(Parser, &StackTop, &VoidType);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if ((int)Token <= (int)TokenCharacterConstant)
|
else if ((int)Token <= (int)TokenCharacterConstant)
|
||||||
{ /* it's a value of some sort, push it */
|
{ /* it's a value of some sort, push it */
|
||||||
if (!PrefixState)
|
if (!PrefixState)
|
||||||
|
@ -926,32 +1056,12 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* parse an expression. operator precedence is not supported */
|
|
||||||
int ExpressionParseInt(struct ParseState *Parser)
|
|
||||||
{
|
|
||||||
struct Value *Val;
|
|
||||||
int Result = 0;
|
|
||||||
|
|
||||||
if (!ExpressionParse(Parser, &Val))
|
|
||||||
ProgramFail(Parser, "expression expected");
|
|
||||||
|
|
||||||
if (Parser->Mode == RunModeRun)
|
|
||||||
{
|
|
||||||
if (Val->Typ->Base != TypeInt)
|
|
||||||
ProgramFail(Parser, "integer value expected");
|
|
||||||
|
|
||||||
Result = Val->Val->Integer;
|
|
||||||
VariableStackPop(Parser, Val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do a function call */
|
/* do a function call */
|
||||||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName)
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName)
|
||||||
{
|
{
|
||||||
|
struct Value *ReturnValue;
|
||||||
struct Value *FuncValue;
|
struct Value *FuncValue;
|
||||||
struct Value *Param;
|
struct Value *Param;
|
||||||
struct Value **ParamArray = NULL;
|
struct Value **ParamArray = NULL;
|
||||||
|
@ -964,7 +1074,8 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Resul
|
||||||
if (FuncValue->Typ->Base != TypeFunction)
|
if (FuncValue->Typ->Base != TypeFunction)
|
||||||
ProgramFail(Parser, "not a function - can't call");
|
ProgramFail(Parser, "not a function - can't call");
|
||||||
|
|
||||||
*Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, FALSE, NULL);
|
ExpressionStackPushValueByType(Parser, StackTop, FuncValue->Val->FuncDef.ReturnType);
|
||||||
|
ReturnValue = (*StackTop)->Val;
|
||||||
HeapPushStackFrame();
|
HeapPushStackFrame();
|
||||||
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
||||||
if (ParamArray == NULL)
|
if (ParamArray == NULL)
|
||||||
|
@ -1018,21 +1129,44 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Resul
|
||||||
|
|
||||||
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
||||||
TopStackFrame->NumParams = ArgCount;
|
TopStackFrame->NumParams = ArgCount;
|
||||||
TopStackFrame->ReturnValue = *Result;
|
TopStackFrame->ReturnValue = ReturnValue;
|
||||||
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
||||||
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]);
|
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]);
|
||||||
|
|
||||||
if (!ParseStatement(&FuncParser))
|
if (!ParseStatement(&FuncParser))
|
||||||
ProgramFail(&FuncParser, "function body expected");
|
ProgramFail(&FuncParser, "function body expected");
|
||||||
|
|
||||||
if (FuncValue->Val->FuncDef.ReturnType != (*Result)->Typ)
|
if (FuncValue->Val->FuncDef.ReturnType != ReturnValue->Typ)
|
||||||
ProgramFail(&FuncParser, "bad type of return value");
|
ProgramFail(&FuncParser, "bad type of return value");
|
||||||
|
|
||||||
VariableStackFramePop(Parser);
|
VariableStackFramePop(Parser);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
FuncValue->Val->FuncDef.Intrinsic(Parser, *Result, ParamArray, ArgCount);
|
FuncValue->Val->FuncDef.Intrinsic(Parser, ReturnValue, ParamArray, ArgCount);
|
||||||
|
|
||||||
HeapPopStackFrame();
|
HeapPopStackFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* parse an expression. operator precedence is not supported */
|
||||||
|
int ExpressionParseInt(struct ParseState *Parser)
|
||||||
|
{
|
||||||
|
struct Value *Val;
|
||||||
|
int Result = 0;
|
||||||
|
|
||||||
|
if (!ExpressionParse(Parser, &Val))
|
||||||
|
ProgramFail(Parser, "expression expected");
|
||||||
|
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{
|
||||||
|
if (Val->Typ->Base != TypeInt)
|
||||||
|
ProgramFail(Parser, "integer value expected");
|
||||||
|
|
||||||
|
Result = Val->Val->Integer;
|
||||||
|
VariableStackPop(Parser, Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue