2009-03-08 03:56:28 -04:00
|
|
|
#include "picoc.h"
|
|
|
|
|
2009-03-11 22:21:12 -04:00
|
|
|
|
|
|
|
/* whether evaluation is left to right for a given precedence level */
|
|
|
|
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 3 && (p) != 14)
|
2009-03-28 07:10:34 -04:00
|
|
|
#define BRACKET_PRECEDENCE 20
|
2009-03-11 22:21:12 -04:00
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
#define debugf printf
|
|
|
|
#else
|
|
|
|
void debugf(char *Format, ...)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
2009-03-11 22:21:12 -04:00
|
|
|
|
2009-04-04 22:24:00 -04:00
|
|
|
/* local prototypes */
|
2009-03-11 22:21:12 -04:00
|
|
|
enum OperatorOrder
|
|
|
|
{
|
2009-03-29 07:08:03 -04:00
|
|
|
OrderNone,
|
2009-03-11 22:21:12 -04:00
|
|
|
OrderPrefix,
|
|
|
|
OrderInfix,
|
|
|
|
OrderPostfix
|
|
|
|
};
|
|
|
|
|
|
|
|
/* a stack of expressions we use in evaluation */
|
|
|
|
struct ExpressionStack
|
|
|
|
{
|
2009-04-13 02:57:32 -04:00
|
|
|
struct ExpressionStack *Next; /* the next lower item on the stack */
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct Value *Val; /* the value for this stack node */
|
|
|
|
enum LexToken Op; /* the operator */
|
|
|
|
} p;
|
|
|
|
short unsigned int Precedence; /* the operator precedence of this node */
|
|
|
|
unsigned char Order; /* the evaluation order of this operator */
|
2009-03-11 22:21:12 -04:00
|
|
|
};
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
/* operator precedence definitions */
|
|
|
|
struct OpPrecedence
|
|
|
|
{
|
|
|
|
unsigned char PrefixPrecedence:4;
|
|
|
|
unsigned char PostfixPrecedence:4;
|
|
|
|
unsigned char InfixPrecedence:4;
|
2009-04-13 02:57:32 -04:00
|
|
|
char *Name;
|
2009-03-08 03:56:28 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct OpPrecedence OperatorPrecedence[] =
|
|
|
|
{
|
2009-04-13 02:57:32 -04:00
|
|
|
/* TokenNone, */ { 0, 0, 0, "none" },
|
|
|
|
/* TokenComma, */ { 0, 0, 0, "," },
|
|
|
|
/* TokenAssign, */ { 0, 0, 2, "=" }, /* TokenAddAssign, */ { 0, 0, 2, "+=" }, /* TokenSubtractAssign, */ { 0, 0, 2, "-=" },
|
|
|
|
/* TokenMultiplyAssign, */ { 0, 0, 2, "*=" }, /* TokenDivideAssign, */ { 0, 0, 2, "/=" }, /* TokenModulusAssign, */ { 0, 0, 2, "%=" },
|
|
|
|
/* TokenShiftLeftAssign, */ { 0, 0, 2, "<<=" }, /* TokenShiftRightAssign, */ { 0, 0, 2, ">>=" }, /* TokenArithmeticAndAssign, */ { 0, 0, 2, "&=" },
|
|
|
|
/* TokenArithmeticOrAssign, */ { 0, 0, 2, "|=" }, /* TokenArithmeticExorAssign, */ { 0, 0, 2, "^=" },
|
|
|
|
/* TokenQuestionMark, */ { 0, 0, 3, "?" }, /* TokenColon, */ { 0, 0, 3, ":" },
|
|
|
|
/* TokenLogicalOr, */ { 0, 0, 4, "||" },
|
|
|
|
/* TokenLogicalAnd, */ { 0, 0, 5, "&&" },
|
|
|
|
/* TokenArithmeticOr, */ { 0, 0, 6, "|" },
|
|
|
|
/* TokenArithmeticExor, */ { 0, 0, 7, "^" },
|
|
|
|
/* TokenAmpersand, */ { 14, 0, 8, "&" },
|
|
|
|
/* TokenEqual, */ { 0, 0, 9, "==" }, /* TokenNotEqual, */ { 0, 0, 9, "!=" },
|
|
|
|
/* TokenLessThan, */ { 0, 0, 10, "<" }, /* TokenGreaterThan, */ { 0, 0, 10, ">" }, /* TokenLessEqual, */ { 0, 0, 10, "<=" }, /* TokenGreaterEqual, */ { 0, 0, 10, ">=" },
|
|
|
|
/* TokenShiftLeft, */ { 0, 0, 11, "<<" }, /* TokenShiftRight, */ { 0, 0, 11, ">>" },
|
|
|
|
/* TokenPlus, */ { 14, 0, 12, "+" }, /* TokenMinus, */ { 14, 0, 12, "-" },
|
|
|
|
/* TokenAsterisk, */ { 14, 0, 13, "*" }, /* TokenSlash, */ { 0, 0, 13, "/" }, /* TokenModulus, */ { 0, 0, 13, "%" },
|
|
|
|
/* TokenIncrement, */ { 14, 15, 0, "++" }, /* TokenDecrement, */ { 14, 15, 0, "--" }, /* TokenUnaryNot, */ { 14, 0, 0, "!" }, /* TokenUnaryExor, */ { 14, 0, 0, "~" }, /* TokenSizeof, */ { 14, 0, 0, "sizeof" },
|
2009-04-14 02:55:00 -04:00
|
|
|
/* TokenLeftSquareBracket, */ { 0, 0, 15, "[" }, /* TokenRightSquareBracket, */ { 0, 15, 0, "]" }, /* TokenDot, */ { 0, 0, 15, "." }, /* TokenArrow, */ { 0, 0, 15, "->" },
|
2009-04-13 02:57:32 -04:00
|
|
|
/* TokenOpenBracket, */ { 15, 0, 0, "(" }, /* TokenCloseBracket, */ { 0, 15, 0, ")" }
|
2009-03-08 03:56:28 -04:00
|
|
|
};
|
|
|
|
|
2009-04-04 22:24:00 -04:00
|
|
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName);
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
/* show the contents of the expression stack */
|
|
|
|
void ExpressionStackShow(struct ExpressionStack *StackTop)
|
|
|
|
{
|
2009-04-15 06:47:51 -04:00
|
|
|
printf("Expression stack [0x%lx,0x%lx]: ", (long)HeapStackTop, (long)StackTop);
|
2009-04-13 02:57:32 -04:00
|
|
|
|
|
|
|
while (StackTop != NULL)
|
|
|
|
{
|
|
|
|
if (StackTop->Order == OrderNone)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* it's a value */
|
2009-04-13 02:57:32 -04:00
|
|
|
if (StackTop->p.Val->IsLValue)
|
|
|
|
printf("lvalue=");
|
|
|
|
else
|
|
|
|
printf("value=");
|
|
|
|
|
|
|
|
switch (StackTop->p.Val->Typ->Base)
|
|
|
|
{
|
2009-04-13 23:18:40 -04:00
|
|
|
case TypeVoid: printf("void"); break;
|
2009-04-13 02:57:32 -04:00
|
|
|
case TypeInt: case TypeChar: printf("%d:int", StackTop->p.Val->Val->Integer); break;
|
|
|
|
case TypeFP: printf("%f:fp", StackTop->p.Val->Val->FP); break;
|
|
|
|
case TypeFunction: printf("%s:function", StackTop->p.Val->Val->Identifier); break;
|
|
|
|
case TypeMacro: printf("%s:macro", StackTop->p.Val->Val->Identifier); break;
|
|
|
|
case TypePointer:
|
|
|
|
if (StackTop->p.Val->Typ->FromType->Base == TypeChar)
|
|
|
|
printf("\"%s\":string", (char *)StackTop->p.Val->Val->Pointer.Segment->Val->Array.Data);
|
|
|
|
else
|
|
|
|
printf("ptr(0x%lx,%d)", (long)StackTop->p.Val->Val->Pointer.Segment, StackTop->p.Val->Val->Pointer.Offset);
|
|
|
|
break;
|
|
|
|
case TypeArray: printf("array"); break;
|
|
|
|
case TypeStruct: printf("%s:struct", StackTop->p.Val->Val->Identifier); break;
|
|
|
|
case TypeUnion: printf("%s:union", StackTop->p.Val->Val->Identifier); break;
|
|
|
|
case TypeEnum: printf("%s:enum", StackTop->p.Val->Val->Identifier); break;
|
|
|
|
default: printf("unknown"); break;
|
|
|
|
}
|
2009-04-15 06:47:51 -04:00
|
|
|
printf("[0x%lx,0x%lx]", (long)StackTop, (long)StackTop->p.Val);
|
2009-04-13 02:57:32 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* it's an operator */
|
|
|
|
printf("op='%s' %s %d", OperatorPrecedence[(int)StackTop->p.Op].Name,
|
|
|
|
(StackTop->Order == OrderPrefix) ? "prefix" : ((StackTop->Order == OrderPostfix) ? "postfix" : "infix"),
|
|
|
|
StackTop->Precedence);
|
2009-04-15 06:47:51 -04:00
|
|
|
printf("[0x%lx]", (long)StackTop);
|
2009-04-13 02:57:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
StackTop = StackTop->Next;
|
|
|
|
if (StackTop != NULL)
|
|
|
|
printf(", ");
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#endif
|
2009-03-28 07:10:34 -04:00
|
|
|
|
2009-04-22 08:06:58 -04:00
|
|
|
/* assign an integer value */
|
|
|
|
int ExpressionAssignInt(struct ParseState *Parser, struct Value *DestValue, int FromInt, int After)
|
|
|
|
{
|
|
|
|
int Result;
|
|
|
|
|
|
|
|
if (!DestValue->IsLValue)
|
|
|
|
ProgramFail(Parser, "can't assign to this");
|
|
|
|
|
|
|
|
if (After)
|
|
|
|
Result = DestValue->Val->Integer;
|
|
|
|
else
|
|
|
|
Result = FromInt;
|
|
|
|
|
|
|
|
DestValue->Val->Integer = FromInt;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-04-22 18:28:30 -04:00
|
|
|
#ifndef NO_FP
|
|
|
|
/* assign a floating point value */
|
2009-04-22 08:06:58 -04:00
|
|
|
int ExpressionAssignFP(struct ParseState *Parser, struct Value *DestValue, double FromFP)
|
|
|
|
{
|
|
|
|
if (!DestValue->IsLValue)
|
|
|
|
ProgramFail(Parser, "can't assign to this");
|
|
|
|
|
|
|
|
DestValue->Val->FP = FromFP;
|
|
|
|
return FromFP;
|
|
|
|
}
|
2009-04-22 18:28:30 -04:00
|
|
|
#endif
|
2009-04-22 08:06:58 -04:00
|
|
|
|
2009-03-28 07:10:34 -04:00
|
|
|
/* push a node on to the expression stack */
|
|
|
|
void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *ValueLoc)
|
|
|
|
{
|
|
|
|
struct ExpressionStack *StackNode = VariableAlloc(Parser, sizeof(struct ExpressionStack), FALSE);
|
|
|
|
StackNode->Next = *StackTop;
|
2009-04-13 02:57:32 -04:00
|
|
|
StackNode->p.Val = ValueLoc;
|
2009-03-28 07:10:34 -04:00
|
|
|
*StackTop = StackNode;
|
2009-04-13 02:57:32 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(*StackTop);
|
|
|
|
#endif
|
2009-03-28 07:10:34 -04:00
|
|
|
}
|
|
|
|
|
2009-04-04 22:24:00 -04:00
|
|
|
/* push a blank value on to the expression stack by type */
|
2009-04-19 07:49:01 -04:00
|
|
|
struct Value *ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType)
|
2009-04-04 22:24:00 -04:00
|
|
|
{
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionStackPushValueByType()\n");
|
2009-04-15 06:47:51 -04:00
|
|
|
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL);
|
2009-04-04 22:24:00 -04:00
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
2009-04-19 07:49:01 -04:00
|
|
|
|
|
|
|
return ValueLoc;
|
2009-04-04 22:24:00 -04:00
|
|
|
}
|
|
|
|
|
2009-03-28 07:10:34 -04:00
|
|
|
/* push a value on to the expression stack */
|
|
|
|
void ExpressionStackPushValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue)
|
|
|
|
{
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionStackPushValue()\n");
|
2009-04-15 06:47:51 -04:00
|
|
|
struct Value *ValueLoc = VariableAllocValueAndCopy(Parser, PushValue, FALSE);
|
2009-04-13 02:57:32 -04:00
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
|
|
|
}
|
|
|
|
|
2009-04-22 03:23:26 -04:00
|
|
|
void ExpressionStackPushLValue(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *PushValue, int Offset)
|
2009-04-13 02:57:32 -04:00
|
|
|
{
|
|
|
|
debugf("ExpressionStackPushLValue()\n");
|
2009-04-15 06:47:51 -04:00
|
|
|
struct Value *ValueLoc = VariableAllocValueShared(Parser, PushValue);
|
2009-04-22 03:23:26 -04:00
|
|
|
ValueLoc->Val = (void *)ValueLoc->Val + Offset;
|
2009-03-28 07:10:34 -04:00
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **StackTop, int IntValue)
|
|
|
|
{
|
2009-04-15 06:47:51 -04:00
|
|
|
debugf("ExpressionPushInt()\n");
|
2009-03-28 07:10:34 -04:00
|
|
|
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
|
|
|
ValueLoc->Val->Integer = IntValue;
|
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
|
|
|
}
|
|
|
|
|
2009-04-18 21:15:01 -04:00
|
|
|
#ifndef NO_FP
|
2009-03-28 07:10:34 -04:00
|
|
|
void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackTop, double FPValue)
|
|
|
|
{
|
2009-04-15 06:47:51 -04:00
|
|
|
debugf("ExpressionPushFP()\n");
|
2009-04-04 22:24:00 -04:00
|
|
|
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL);
|
2009-03-28 07:10:34 -04:00
|
|
|
ValueLoc->Val->FP = FPValue;
|
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
|
|
|
|
}
|
2009-04-18 21:15:01 -04:00
|
|
|
#endif
|
2009-03-28 07:10:34 -04:00
|
|
|
|
2009-03-12 06:49:57 -04:00
|
|
|
/* evaluate a prefix operator */
|
2009-03-28 07:10:34 -04:00
|
|
|
void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
2009-03-28 07:10:34 -04:00
|
|
|
struct Value *TempLValue;
|
|
|
|
struct Value *Result;
|
|
|
|
|
2009-04-13 05:02:45 -04:00
|
|
|
if (Parser->Mode != RunModeRun)
|
|
|
|
{
|
|
|
|
/* we're not running it so just return 0 */
|
|
|
|
ExpressionPushInt(Parser, StackTop, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionPrefixOperator()\n");
|
2009-03-28 07:10:34 -04:00
|
|
|
switch (Op)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
|
|
|
case TokenAmpersand:
|
|
|
|
if (!TopValue->IsLValue)
|
|
|
|
ProgramFail(Parser, "can't get the address of this");
|
|
|
|
|
|
|
|
TempLValue = TopValue->LValueFrom;
|
|
|
|
Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, TopValue->Typ, TypePointer, 0, StrEmpty), FALSE, NULL);
|
|
|
|
Result->Val->Pointer.Segment = TempLValue;
|
2009-04-22 03:23:26 -04:00
|
|
|
if (Result->LValueFrom != NULL)
|
|
|
|
Result->Val->Pointer.Offset = (void *)Result->Val - (void *)Result->LValueFrom;
|
|
|
|
|
2009-03-12 06:49:57 -04:00
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
|
|
|
break;
|
2009-03-28 07:10:34 -04:00
|
|
|
|
2009-03-12 06:49:57 -04:00
|
|
|
case TokenAsterisk:
|
2009-04-22 03:23:26 -04:00
|
|
|
VariableCheckPointer(Parser, TopValue);
|
|
|
|
ExpressionStackPushLValue(Parser, StackTop, TopValue->Val->Pointer.Segment, TopValue->Val->Pointer.Offset);
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenSizeof:
|
|
|
|
// XXX
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenLeftSquareBracket:
|
|
|
|
// XXX
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenOpenBracket:
|
2009-04-14 02:55:00 -04:00
|
|
|
// XXX - cast
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* an arithmetic operator */
|
|
|
|
if (IS_INTEGER_COERCIBLE(TopValue))
|
|
|
|
{
|
|
|
|
/* integer prefix arithmetic */
|
2009-04-18 21:15:01 -04:00
|
|
|
int ResultInt = 0;
|
2009-03-12 06:49:57 -04:00
|
|
|
int TopInt = COERCE_INTEGER(TopValue);
|
2009-03-28 07:10:34 -04:00
|
|
|
switch (Op)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
|
|
|
case TokenPlus: ResultInt = TopInt; break;
|
|
|
|
case TokenMinus: ResultInt = -TopInt; break;
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, FALSE); break;
|
|
|
|
case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, FALSE); break;
|
2009-03-12 06:49:57 -04:00
|
|
|
case TokenUnaryNot: ResultInt = !TopInt; break;
|
|
|
|
case TokenUnaryExor: ResultInt = ~TopInt; break;
|
2009-03-28 07:10:34 -04:00
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
|
|
|
}
|
|
|
|
#ifndef NO_FP
|
|
|
|
else if (TopValue->Typ == &FPType)
|
|
|
|
{
|
|
|
|
/* floating point prefix arithmetic */
|
2009-03-28 07:10:34 -04:00
|
|
|
double ResultFP;
|
|
|
|
switch (Op)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
|
|
|
case TokenPlus: ResultFP = TopValue->Val->FP; break;
|
|
|
|
case TokenMinus: ResultFP = -TopValue->Val->FP; break;
|
2009-03-28 07:10:34 -04:00
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-03-28 07:10:34 -04:00
|
|
|
#if 0
|
|
|
|
XXX - finish this
|
2009-03-12 06:49:57 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* pointer prefix arithmetic */
|
|
|
|
int TopInt = COERCE_INTEGER(TopValue);
|
|
|
|
}
|
2009-03-28 07:10:34 -04:00
|
|
|
#endif
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* evaluate a postfix operator */
|
2009-03-28 07:10:34 -04:00
|
|
|
void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
2009-04-13 05:02:45 -04:00
|
|
|
if (Parser->Mode != RunModeRun)
|
|
|
|
{
|
|
|
|
/* we're not running it so just return 0 */
|
|
|
|
ExpressionPushInt(Parser, StackTop, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionPostfixOperator()\n");
|
2009-03-12 06:49:57 -04:00
|
|
|
if (IS_INTEGER_COERCIBLE(TopValue))
|
|
|
|
{
|
2009-04-18 21:15:01 -04:00
|
|
|
int ResultInt = 0;
|
2009-03-12 06:49:57 -04:00
|
|
|
int TopInt = COERCE_INTEGER(TopValue);
|
2009-03-28 07:10:34 -04:00
|
|
|
switch (Op)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenIncrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt+1, TRUE); break;
|
|
|
|
case TokenDecrement: ResultInt = ExpressionAssignInt(Parser, TopValue, TopInt-1, TRUE); break;
|
2009-03-12 06:49:57 -04:00
|
|
|
case TokenRightSquareBracket: break; // XXX
|
|
|
|
case TokenCloseBracket: break; // XXX
|
2009-03-28 07:10:34 -04:00
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
|
2009-03-28 07:10:34 -04:00
|
|
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
|
|
|
}
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* evaluate an infix operator */
|
2009-03-28 07:10:34 -04:00
|
|
|
void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *BottomValue, struct Value *TopValue)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
2009-04-18 21:15:01 -04:00
|
|
|
int ResultInt = 0;
|
2009-04-22 04:19:52 -04:00
|
|
|
struct PointerValue Pointer;
|
|
|
|
struct Value *StackValue;
|
2009-03-28 07:10:34 -04:00
|
|
|
|
2009-04-13 05:02:45 -04:00
|
|
|
if (Parser->Mode != RunModeRun)
|
|
|
|
{
|
|
|
|
/* we're not running it so just return 0 */
|
|
|
|
ExpressionPushInt(Parser, StackTop, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionInfixOperator()\n");
|
2009-04-14 02:55:00 -04:00
|
|
|
if (Op == TokenLeftSquareBracket)
|
|
|
|
{
|
|
|
|
/* array index */
|
|
|
|
int ArrayIndex;
|
|
|
|
struct Value *Result;
|
|
|
|
|
|
|
|
if (BottomValue->Typ->Base != TypeArray)
|
|
|
|
ProgramFail(Parser, "not an array");
|
|
|
|
|
|
|
|
if (!IS_INTEGER_COERCIBLE(TopValue))
|
|
|
|
ProgramFail(Parser, "array index must be an integer");
|
|
|
|
|
|
|
|
ArrayIndex = COERCE_INTEGER(TopValue);
|
|
|
|
if (ArrayIndex < 0 || ArrayIndex >= BottomValue->Val->Array.Size)
|
|
|
|
ProgramFail(Parser, "illegal array index %d [0..%d]", ArrayIndex, BottomValue->Val->Array.Size-1);
|
|
|
|
|
|
|
|
/* make the array element result */
|
2009-04-22 08:06:58 -04:00
|
|
|
// XXX - need to handle char array access
|
2009-04-14 02:55:00 -04:00
|
|
|
Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)(BottomValue->Val->Array.Data + TypeSize(BottomValue->Typ->FromType, 0) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom);
|
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
|
|
|
}
|
|
|
|
else if (IS_INTEGER_COERCIBLE(TopValue) && IS_INTEGER_COERCIBLE(BottomValue))
|
|
|
|
{
|
|
|
|
/* integer operation */
|
2009-04-13 23:18:40 -04:00
|
|
|
int TopInt = COERCE_INTEGER(TopValue);
|
|
|
|
int BottomInt = COERCE_INTEGER(BottomValue);
|
|
|
|
switch (Op)
|
|
|
|
{
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, TopInt, FALSE); break;
|
|
|
|
case TokenAddAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt + TopInt, FALSE); break;
|
|
|
|
case TokenSubtractAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt - TopInt, FALSE); break;
|
|
|
|
case TokenMultiplyAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt * TopInt, FALSE); break;
|
|
|
|
case TokenDivideAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt / TopInt, FALSE); break;
|
2009-04-18 21:15:01 -04:00
|
|
|
#ifndef NO_MODULUS
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenModulusAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt % TopInt, FALSE); break;
|
2009-04-18 21:15:01 -04:00
|
|
|
#endif
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenShiftLeftAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt << TopInt, FALSE); break;
|
|
|
|
case TokenShiftRightAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt >> TopInt, FALSE); break;
|
|
|
|
case TokenArithmeticAndAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt & TopInt, FALSE); break;
|
|
|
|
case TokenArithmeticOrAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt | TopInt, FALSE); break;
|
|
|
|
case TokenArithmeticExorAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt ^ TopInt, FALSE); break;
|
2009-04-13 23:18:40 -04:00
|
|
|
case TokenQuestionMark: break; // XXX
|
|
|
|
case TokenColon: break; // XXX
|
|
|
|
case TokenLogicalOr: ResultInt = BottomInt || TopInt; break;
|
|
|
|
case TokenLogicalAnd: ResultInt = BottomInt && TopInt; break;
|
|
|
|
case TokenArithmeticOr: ResultInt = BottomInt | TopInt; break;
|
|
|
|
case TokenArithmeticExor: ResultInt = BottomInt ^ TopInt; break;
|
|
|
|
case TokenAmpersand: ResultInt = BottomInt & TopInt; break;
|
|
|
|
case TokenEqual: ResultInt = BottomInt == TopInt; break;
|
|
|
|
case TokenNotEqual: ResultInt = BottomInt != TopInt; break;
|
|
|
|
case TokenLessThan: ResultInt = BottomInt < TopInt; break;
|
|
|
|
case TokenGreaterThan: ResultInt = BottomInt > TopInt; break;
|
|
|
|
case TokenLessEqual: ResultInt = BottomInt <= TopInt; break;
|
|
|
|
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; break;
|
|
|
|
case TokenShiftLeft: ResultInt = BottomInt << TopInt; break;
|
|
|
|
case TokenShiftRight: ResultInt = BottomInt << TopInt; break;
|
|
|
|
case TokenPlus: ResultInt = BottomInt + TopInt; break;
|
|
|
|
case TokenMinus: ResultInt = BottomInt - TopInt; break;
|
|
|
|
case TokenAsterisk: ResultInt = BottomInt * TopInt; break;
|
|
|
|
case TokenSlash: ResultInt = BottomInt / TopInt; break;
|
2009-04-18 21:15:01 -04:00
|
|
|
#ifndef NO_MODULUS
|
2009-04-13 23:18:40 -04:00
|
|
|
case TokenModulus: ResultInt = BottomInt % TopInt; break;
|
2009-04-18 21:15:01 -04:00
|
|
|
#endif
|
2009-04-13 23:18:40 -04:00
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
|
|
|
}
|
2009-03-12 06:49:57 -04:00
|
|
|
#ifndef NO_FP
|
2009-04-13 23:18:40 -04:00
|
|
|
else if ( (TopValue->Typ == &FPType && BottomValue->Typ == &FPType) ||
|
|
|
|
(TopValue->Typ == &FPType && IS_INTEGER_COERCIBLE(BottomValue)) ||
|
|
|
|
(IS_INTEGER_COERCIBLE(TopValue) && BottomValue->Typ == &FPType) )
|
|
|
|
{
|
|
|
|
/* floating point infix arithmetic */
|
2009-04-18 21:15:01 -04:00
|
|
|
int ResultIsInt = FALSE;
|
|
|
|
double ResultFP = 0.0;
|
2009-04-13 23:18:40 -04:00
|
|
|
double TopFP = (TopValue->Typ == &FPType) ? TopValue->Val->FP : (double)COERCE_INTEGER(TopValue);
|
|
|
|
double BottomFP = (BottomValue->Typ == &FPType) ? BottomValue->Val->FP : (double)COERCE_INTEGER(BottomValue);
|
2009-03-12 06:49:57 -04:00
|
|
|
|
2009-04-13 23:18:40 -04:00
|
|
|
switch (Op)
|
|
|
|
{
|
2009-04-22 08:06:58 -04:00
|
|
|
case TokenAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, TopFP); break;
|
|
|
|
case TokenAddAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP + TopFP); break;
|
|
|
|
case TokenSubtractAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP - TopFP); break;
|
|
|
|
case TokenMultiplyAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP * TopFP); break;
|
|
|
|
case TokenDivideAssign: ResultFP = ExpressionAssignFP(Parser, BottomValue, BottomFP / TopFP); break;
|
2009-04-13 23:18:40 -04:00
|
|
|
case TokenEqual: ResultInt = BottomFP == TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenNotEqual: ResultInt = BottomFP != TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenLessThan: ResultInt = BottomFP < TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenGreaterThan: ResultInt = BottomFP > TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenLessEqual: ResultInt = BottomFP <= TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenGreaterEqual: ResultInt = BottomFP >= TopFP; ResultIsInt = TRUE; break;
|
|
|
|
case TokenPlus: ResultFP = BottomFP + TopFP; break;
|
|
|
|
case TokenMinus: ResultFP = BottomFP - TopFP; break;
|
|
|
|
case TokenAsterisk: ResultFP = BottomFP * TopFP; break;
|
|
|
|
case TokenSlash: ResultFP = BottomFP / TopFP; break;
|
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
|
|
|
}
|
2009-03-12 06:49:57 -04:00
|
|
|
|
2009-04-13 23:18:40 -04:00
|
|
|
if (ResultIsInt)
|
|
|
|
ExpressionPushInt(Parser, StackTop, ResultInt);
|
|
|
|
else
|
|
|
|
ExpressionPushFP(Parser, StackTop, ResultFP);
|
|
|
|
}
|
2009-03-12 06:49:57 -04:00
|
|
|
#endif
|
2009-04-19 07:49:01 -04:00
|
|
|
else if (BottomValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(TopValue))
|
2009-04-13 23:18:40 -04:00
|
|
|
{
|
2009-04-19 07:49:01 -04:00
|
|
|
/* pointer/integer infix arithmetic */
|
|
|
|
int TopInt = COERCE_INTEGER(TopValue);
|
|
|
|
|
|
|
|
if (Op == TokenEqual || Op == TokenNotEqual)
|
2009-04-13 23:18:40 -04:00
|
|
|
{
|
2009-04-19 07:49:01 -04:00
|
|
|
/* comparison to a NULL pointer */
|
|
|
|
if (TopInt != 0)
|
|
|
|
ProgramFail(Parser, "invalid operation");
|
|
|
|
|
|
|
|
if (Op == TokenEqual)
|
|
|
|
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment == NULL);
|
|
|
|
else
|
|
|
|
ExpressionPushInt(Parser, StackTop, BottomValue->Val->Pointer.Segment != NULL);
|
|
|
|
}
|
|
|
|
else if (Op == TokenPlus || Op == TokenMinus)
|
|
|
|
{
|
|
|
|
/* pointer arithmetic */
|
|
|
|
int Size = TypeSize(BottomValue->Typ->FromType, 0);
|
|
|
|
|
|
|
|
Pointer = BottomValue->Val->Pointer;
|
|
|
|
if (Pointer.Segment == NULL)
|
|
|
|
ProgramFail(Parser, "invalid use of a NULL pointer");
|
|
|
|
|
|
|
|
if (Op == TokenPlus)
|
|
|
|
Pointer.Offset += TopInt * Size;
|
|
|
|
else
|
|
|
|
Pointer.Offset -= TopInt * Size;
|
|
|
|
|
|
|
|
/* check pointer bounds */
|
2009-04-22 04:19:52 -04:00
|
|
|
if (Pointer.Offset < 0 || Pointer.Offset > TypeLastAccessibleOffset(Pointer.Segment))
|
2009-04-19 07:49:01 -04:00
|
|
|
Pointer.Offset = BottomValue->Val->Pointer.Offset;
|
|
|
|
|
|
|
|
StackValue = ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ);
|
|
|
|
StackValue->Val->Pointer = Pointer;
|
|
|
|
}
|
|
|
|
else if (Op == TokenAssign && TopInt == 0)
|
|
|
|
{
|
|
|
|
/* assign a NULL pointer */
|
|
|
|
if (!BottomValue->IsLValue)
|
|
|
|
ProgramFail(Parser, "can't assign to this");
|
|
|
|
|
|
|
|
ExpressionStackPushValueByType(Parser, StackTop, BottomValue->Typ);
|
2009-04-13 23:18:40 -04:00
|
|
|
}
|
|
|
|
else
|
2009-04-19 07:49:01 -04:00
|
|
|
ProgramFail(Parser, "invalid operation");
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
2009-04-22 04:19:52 -04:00
|
|
|
else if (BottomValue->Typ->Base == TypePointer && TopValue->Typ->Base == TypePointer && Op != TokenAssign)
|
|
|
|
{
|
|
|
|
/* pointer/pointer operations */
|
|
|
|
void *TopLoc = (void *)TopValue->Val->Pointer.Segment->Val + TopValue->Val->Pointer.Offset;
|
|
|
|
void *BottomLoc = (void *)BottomValue->Val->Pointer.Segment->Val + BottomValue->Val->Pointer.Offset;
|
|
|
|
|
|
|
|
switch (Op)
|
|
|
|
{
|
|
|
|
case TokenEqual: ExpressionPushInt(Parser, StackTop, BottomLoc == TopLoc); break;
|
|
|
|
case TokenNotEqual: ExpressionPushInt(Parser, StackTop, BottomLoc != TopLoc); break;
|
|
|
|
case TokenMinus: ExpressionPushInt(Parser, StackTop, BottomLoc - TopLoc); break;
|
|
|
|
default: ProgramFail(Parser, "invalid operation"); break;
|
|
|
|
}
|
|
|
|
}
|
2009-04-15 01:26:46 -04:00
|
|
|
else if (Op == TokenAssign)
|
|
|
|
{
|
|
|
|
/* assign a non-numeric type */
|
|
|
|
if (!BottomValue->IsLValue)
|
|
|
|
ProgramFail(Parser, "can't assign to this");
|
|
|
|
|
|
|
|
if (BottomValue->Typ != TopValue->Typ)
|
|
|
|
ProgramFail(Parser, "can't assign to a different type of variable");
|
|
|
|
|
2009-04-18 21:15:01 -04:00
|
|
|
memcpy((void *)BottomValue->Val, (void *)TopValue->Val, TypeSizeValue(TopValue)); // XXX - need to handle arrays
|
2009-04-15 01:26:46 -04:00
|
|
|
ExpressionStackPushValue(Parser, StackTop, TopValue);
|
|
|
|
}
|
2009-04-13 23:18:40 -04:00
|
|
|
else
|
|
|
|
ProgramFail(Parser, "invalid operation");
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
|
2009-03-08 04:40:05 -04:00
|
|
|
/* take the contents of the expression stack and compute the top until there's nothing greater than the given precedence */
|
|
|
|
void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack **StackTop, int Precedence)
|
|
|
|
{
|
2009-03-12 06:49:57 -04:00
|
|
|
int FoundPrecedence = Precedence;
|
|
|
|
struct Value *TopValue;
|
|
|
|
struct Value *BottomValue;
|
|
|
|
struct ExpressionStack *TopStackNode = *StackTop;
|
|
|
|
struct ExpressionStack *TopOperatorNode;
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionStackCollapse():\n");
|
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(*StackTop);
|
|
|
|
#endif
|
2009-03-29 07:08:03 -04:00
|
|
|
while (TopStackNode != NULL && TopStackNode->Next != NULL && FoundPrecedence >= Precedence)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
|
|
|
/* find the top operator on the stack */
|
2009-04-13 05:02:45 -04:00
|
|
|
if (TopStackNode->Order == OrderNone)
|
2009-03-12 06:49:57 -04:00
|
|
|
TopOperatorNode = TopStackNode->Next;
|
|
|
|
else
|
|
|
|
TopOperatorNode = TopStackNode;
|
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
FoundPrecedence = TopOperatorNode->Precedence;
|
|
|
|
|
2009-03-12 06:49:57 -04:00
|
|
|
/* does it have a high enough precedence? */
|
2009-03-29 07:08:03 -04:00
|
|
|
if (FoundPrecedence >= Precedence && TopOperatorNode != NULL)
|
2009-03-12 06:49:57 -04:00
|
|
|
{
|
|
|
|
/* execute this operator */
|
|
|
|
switch (TopOperatorNode->Order)
|
|
|
|
{
|
|
|
|
case OrderPrefix:
|
|
|
|
/* prefix evaluation */
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("prefix evaluation\n");
|
|
|
|
TopValue = TopStackNode->p.Val;
|
2009-03-12 06:49:57 -04:00
|
|
|
|
|
|
|
/* pop the value and then the prefix operator - assume they'll still be there until we're done */
|
2009-04-13 02:57:32 -04:00
|
|
|
HeapPopStack(TopOperatorNode, sizeof(struct ExpressionStack)*2 + sizeof(struct Value) + TypeStackSizeValue(TopValue));
|
2009-04-13 05:02:45 -04:00
|
|
|
*StackTop = TopOperatorNode->Next;
|
2009-03-12 06:49:57 -04:00
|
|
|
|
|
|
|
/* do the prefix operation */
|
2009-04-13 02:57:32 -04:00
|
|
|
ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->p.Op, TopValue);
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OrderPostfix:
|
|
|
|
/* postfix evaluation */
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("postfix evaluation\n");
|
|
|
|
TopValue = TopStackNode->Next->p.Val;
|
2009-03-12 06:49:57 -04:00
|
|
|
|
2009-04-13 05:02:45 -04:00
|
|
|
/* pop the postfix operator and then the value - assume they'll still be there until we're done */
|
|
|
|
HeapPopStack(TopValue, sizeof(struct ExpressionStack)*2 + sizeof(struct Value) + TypeStackSizeValue(TopValue));
|
2009-03-28 07:10:34 -04:00
|
|
|
*StackTop = TopStackNode->Next->Next;
|
2009-03-12 06:49:57 -04:00
|
|
|
|
|
|
|
/* do the postfix operation */
|
2009-04-13 02:57:32 -04:00
|
|
|
ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->p.Op, TopValue);
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OrderInfix:
|
|
|
|
/* infix evaluation */
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("infix evaluation\n");
|
|
|
|
TopValue = TopStackNode->p.Val;
|
|
|
|
BottomValue = TopOperatorNode->Next->p.Val;
|
|
|
|
|
|
|
|
/* pop a value, the operator and another value - assume they'll still be there until we're done */
|
|
|
|
HeapPopStack(BottomValue, sizeof(struct ExpressionStack)*3 + sizeof(struct Value)*2 + TypeStackSizeValue(TopValue) + TypeStackSizeValue(BottomValue));
|
|
|
|
*StackTop = TopOperatorNode->Next->Next;
|
2009-03-12 06:49:57 -04:00
|
|
|
|
|
|
|
/* do the infix operation */
|
2009-04-13 02:57:32 -04:00
|
|
|
ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->p.Op, BottomValue, TopValue);
|
2009-03-12 06:49:57 -04:00
|
|
|
break;
|
2009-03-29 07:08:03 -04:00
|
|
|
|
|
|
|
case OrderNone:
|
|
|
|
break;
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
|
|
|
}
|
2009-04-13 02:57:32 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(*StackTop);
|
|
|
|
#endif
|
|
|
|
TopStackNode = *StackTop;
|
2009-03-12 06:49:57 -04:00
|
|
|
}
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionStackCollapse() finished\n");
|
2009-04-15 06:47:51 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(*StackTop);
|
|
|
|
#endif
|
2009-03-08 04:40:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* push an operator on to the expression stack */
|
2009-03-12 06:49:57 -04:00
|
|
|
void ExpressionStackPushOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum OperatorOrder Order, enum LexToken Token, int Precedence)
|
2009-03-08 04:40:05 -04:00
|
|
|
{
|
2009-03-11 22:21:12 -04:00
|
|
|
struct ExpressionStack *StackNode = VariableAlloc(Parser, sizeof(struct ExpressionStack), FALSE);
|
|
|
|
StackNode->Next = *StackTop;
|
|
|
|
StackNode->Order = Order;
|
2009-04-13 02:57:32 -04:00
|
|
|
StackNode->p.Op = Token;
|
2009-03-11 22:21:12 -04:00
|
|
|
StackNode->Precedence = Precedence;
|
|
|
|
*StackTop = StackNode;
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionStackPushOperator()\n");
|
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(*StackTop);
|
|
|
|
#endif
|
2009-03-08 04:40:05 -04:00
|
|
|
}
|
|
|
|
|
2009-04-13 23:18:40 -04:00
|
|
|
/* do the '.' and '->' operators */
|
|
|
|
void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Token)
|
|
|
|
{
|
|
|
|
struct Value *Ident;
|
|
|
|
|
|
|
|
/* get the identifier following the '.' or '->' */
|
|
|
|
if (LexGetToken(Parser, &Ident, TRUE) != TokenIdentifier)
|
|
|
|
ProgramFail(Parser, "need an structure or union member after '%s'", (Token == TokenDot) ? "." : "->");
|
|
|
|
|
|
|
|
if (Parser->Mode == RunModeRun)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* look up the struct element */
|
2009-04-15 02:40:56 -04:00
|
|
|
struct Value *ParamVal = (*StackTop)->p.Val;
|
|
|
|
struct Value *StructVal = ParamVal;
|
2009-04-22 03:23:26 -04:00
|
|
|
int StructOffset = 0;
|
2009-04-13 23:18:40 -04:00
|
|
|
struct Value *MemberValue;
|
|
|
|
struct Value *Result;
|
|
|
|
|
|
|
|
if (Token == TokenArrow)
|
2009-04-15 02:40:56 -04:00
|
|
|
{
|
|
|
|
/* dereference the struct pointer first */
|
2009-04-22 03:23:26 -04:00
|
|
|
VariableCheckPointer(Parser, ParamVal);
|
2009-04-15 02:40:56 -04:00
|
|
|
StructVal = ParamVal->Val->Pointer.Segment;
|
2009-04-22 03:23:26 -04:00
|
|
|
StructOffset = ParamVal->Val->Pointer.Offset;
|
2009-04-15 02:40:56 -04:00
|
|
|
}
|
2009-04-13 23:18:40 -04:00
|
|
|
|
|
|
|
if (StructVal->Typ->Base != TypeStruct && StructVal->Typ->Base != TypeUnion)
|
|
|
|
ProgramFail(Parser, "can't use '%s' on something that's not a struct or union %s", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "");
|
|
|
|
|
|
|
|
if (!TableGet(StructVal->Typ->Members, Ident->Val->Identifier, &MemberValue))
|
|
|
|
ProgramFail(Parser, "doesn't have a member called '%s'", Ident->Val->Identifier);
|
|
|
|
|
|
|
|
/* pop the value - assume it'll still be there until we're done */
|
2009-04-15 02:40:56 -04:00
|
|
|
HeapPopStack(ParamVal, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StructVal));
|
2009-04-13 23:18:40 -04:00
|
|
|
*StackTop = (*StackTop)->Next;
|
|
|
|
|
|
|
|
/* make the result value for this member only */
|
2009-04-22 03:23:26 -04:00
|
|
|
Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)StructVal->Val + StructOffset + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom);
|
2009-04-13 23:18:40 -04:00
|
|
|
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
/* parse an expression with operator precedence */
|
|
|
|
int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|
|
|
{
|
|
|
|
struct Value *LexValue;
|
2009-03-29 07:08:03 -04:00
|
|
|
int PrefixState = TRUE;
|
2009-03-28 07:10:34 -04:00
|
|
|
int Done = FALSE;
|
2009-03-08 03:56:28 -04:00
|
|
|
int BracketPrecedence = 0;
|
2009-03-11 22:21:12 -04:00
|
|
|
int LocalPrecedence;
|
2009-03-08 03:56:28 -04:00
|
|
|
int Precedence = 0;
|
2009-03-08 04:40:05 -04:00
|
|
|
struct ExpressionStack *StackTop = NULL;
|
2009-04-14 04:44:47 -04:00
|
|
|
int TernaryDepth = 0;
|
2009-03-08 03:56:28 -04:00
|
|
|
|
2009-04-14 04:44:47 -04:00
|
|
|
debugf("ExpressionParse():\n");
|
2009-03-08 03:56:28 -04:00
|
|
|
do
|
|
|
|
{
|
2009-03-30 07:16:40 -04:00
|
|
|
struct ParseState PreState = *Parser;
|
2009-03-08 03:56:28 -04:00
|
|
|
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
2009-04-14 19:44:49 -04:00
|
|
|
if ( ( ( (int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) ||
|
|
|
|
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
|
|
|
(Token != TokenColon || TernaryDepth != 0) )
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
2009-04-14 19:44:49 -04:00
|
|
|
if (Token == TokenColon)
|
|
|
|
printf("It's a colon\n");
|
|
|
|
|
2009-04-14 02:55:00 -04:00
|
|
|
/* it's an operator with precedence */
|
2009-03-08 03:56:28 -04:00
|
|
|
if (PrefixState)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* expect a prefix operator */
|
2009-03-08 03:56:28 -04:00
|
|
|
if (OperatorPrecedence[(int)Token].PrefixPrecedence == 0)
|
|
|
|
ProgramFail(Parser, "operator not expected here");
|
|
|
|
|
2009-04-13 05:02:45 -04:00
|
|
|
LocalPrecedence = OperatorPrecedence[(int)Token].PrefixPrecedence;
|
|
|
|
Precedence = BracketPrecedence + LocalPrecedence;
|
2009-04-14 02:55:00 -04:00
|
|
|
if (Token == TokenOpenBracket)
|
|
|
|
{
|
|
|
|
/* boost the bracket operator precedence, then push */
|
2009-04-13 05:02:45 -04:00
|
|
|
BracketPrecedence += BRACKET_PRECEDENCE;
|
|
|
|
}
|
|
|
|
else
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* scan and collapse the stack to the precedence of this operator, then push */
|
2009-04-13 05:02:45 -04:00
|
|
|
ExpressionStackCollapse(Parser, &StackTop, Precedence);
|
|
|
|
ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* expect an infix or postfix operator */
|
2009-03-08 03:56:28 -04:00
|
|
|
if (OperatorPrecedence[(int)Token].PostfixPrecedence != 0)
|
|
|
|
{
|
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenCloseBracket:
|
2009-04-14 02:55:00 -04:00
|
|
|
case TokenRightSquareBracket:
|
2009-03-08 03:56:28 -04:00
|
|
|
if (BracketPrecedence == 0)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* assume this bracket is after the end of the expression */
|
2009-04-13 02:57:32 -04:00
|
|
|
*Parser = PreState;
|
2009-03-28 07:10:34 -04:00
|
|
|
Done = TRUE;
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
BracketPrecedence -= BRACKET_PRECEDENCE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-03-08 04:40:05 -04:00
|
|
|
/* scan and collapse the stack to the precedence of this operator, then push */
|
|
|
|
Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].PostfixPrecedence;
|
|
|
|
ExpressionStackCollapse(Parser, &StackTop, Precedence);
|
|
|
|
ExpressionStackPushOperator(Parser, &StackTop, OrderPostfix, Token, Precedence);
|
2009-03-08 03:56:28 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* scan and collapse the stack, then push */
|
2009-04-13 23:18:40 -04:00
|
|
|
if (Token == TokenDot || Token == TokenArrow)
|
|
|
|
ExpressionGetStructElement(Parser, &StackTop, Token); /* this operator is followed by a struct element so handle it as a special case */
|
2009-03-12 06:49:57 -04:00
|
|
|
else
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* a standard infix operator */
|
2009-04-13 23:18:40 -04:00
|
|
|
Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].InfixPrecedence;
|
|
|
|
|
|
|
|
/* for right to left order, only go down to the next higher precedence so we evaluate it in reverse order */
|
|
|
|
/* for left to right order, collapse down to this precedence so we evaluate it in forward order */
|
|
|
|
if (IS_LEFT_TO_RIGHT(OperatorPrecedence[(int)Token].InfixPrecedence))
|
|
|
|
ExpressionStackCollapse(Parser, &StackTop, Precedence);
|
|
|
|
else
|
|
|
|
ExpressionStackCollapse(Parser, &StackTop, Precedence+1);
|
2009-03-12 06:49:57 -04:00
|
|
|
|
2009-04-13 23:18:40 -04:00
|
|
|
ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, Token, Precedence);
|
|
|
|
PrefixState = TRUE;
|
|
|
|
}
|
2009-04-14 02:55:00 -04:00
|
|
|
|
|
|
|
/* treat an open square bracket as an infix array index operator followed by an open bracket */
|
|
|
|
if (Token == TokenLeftSquareBracket)
|
|
|
|
{
|
|
|
|
/* boost the bracket operator precedence, then push */
|
|
|
|
BracketPrecedence += BRACKET_PRECEDENCE;
|
|
|
|
}
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ProgramFail(Parser, "operator not expected here");
|
|
|
|
}
|
|
|
|
}
|
2009-04-04 22:24:00 -04:00
|
|
|
else if (Token == TokenIdentifier)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* it's a variable, function or a macro */
|
2009-04-04 22:24:00 -04:00
|
|
|
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)
|
|
|
|
{
|
2009-04-15 02:57:02 -04:00
|
|
|
/* evaluate a macro as a kind of simple subroutine */
|
2009-04-04 22:24:00 -04:00
|
|
|
struct ParseState MacroParser = VariableValue->Val->Parser;
|
2009-04-15 02:57:02 -04:00
|
|
|
struct Value *MacroResult;
|
2009-04-04 22:24:00 -04:00
|
|
|
|
2009-04-15 02:57:02 -04:00
|
|
|
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
2009-04-04 22:24:00 -04:00
|
|
|
ProgramFail(&MacroParser, "expression expected");
|
2009-04-15 02:57:02 -04:00
|
|
|
|
|
|
|
ExpressionStackPushValueNode(Parser, &StackTop, MacroResult);
|
2009-04-04 22:24:00 -04:00
|
|
|
}
|
|
|
|
else if (VariableValue->Typ == TypeVoid)
|
|
|
|
ProgramFail(Parser, "a void value isn't much use here");
|
|
|
|
else
|
2009-04-22 03:23:26 -04:00
|
|
|
ExpressionStackPushLValue(Parser, &StackTop, VariableValue, 0); /* it's a value variable */
|
2009-04-04 22:24:00 -04:00
|
|
|
}
|
|
|
|
else /* push a dummy value */
|
2009-04-13 05:02:45 -04:00
|
|
|
ExpressionPushInt(Parser, &StackTop, 0);
|
2009-04-04 22:24:00 -04:00
|
|
|
}
|
2009-04-15 06:47:51 -04:00
|
|
|
|
|
|
|
PrefixState = FALSE;
|
2009-04-04 22:24:00 -04:00
|
|
|
}
|
2009-04-14 04:44:47 -04:00
|
|
|
else if ((int)Token > TokenCloseBracket && (int)Token <= TokenCharacterConstant)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* it's a value of some sort, push it */
|
2009-03-08 03:56:28 -04:00
|
|
|
if (!PrefixState)
|
|
|
|
ProgramFail(Parser, "value not expected here");
|
|
|
|
|
2009-03-28 07:10:34 -04:00
|
|
|
PrefixState = FALSE;
|
2009-03-08 04:40:05 -04:00
|
|
|
ExpressionStackPushValue(Parser, &StackTop, LexValue);
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
else
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* it isn't a token from an expression */
|
2009-03-30 07:16:40 -04:00
|
|
|
*Parser = PreState;
|
2009-03-28 07:10:34 -04:00
|
|
|
Done = TRUE;
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
} while (!Done);
|
2009-03-08 04:40:05 -04:00
|
|
|
|
2009-04-14 04:44:47 -04:00
|
|
|
/* check that brackets have been closed */
|
|
|
|
if (BracketPrecedence > 0)
|
|
|
|
ProgramFail(Parser, "brackets not closed");
|
|
|
|
|
2009-03-08 04:40:05 -04:00
|
|
|
/* scan and collapse the stack to precedence 0 */
|
|
|
|
ExpressionStackCollapse(Parser, &StackTop, 0);
|
2009-03-29 07:08:03 -04:00
|
|
|
|
|
|
|
/* fix up the stack and return the result if we're in run mode */
|
|
|
|
if (StackTop != NULL)
|
|
|
|
{
|
|
|
|
/* all that should be left is a single value on the stack */
|
2009-03-30 07:16:40 -04:00
|
|
|
if (Parser->Mode == RunModeRun)
|
2009-04-15 06:47:51 -04:00
|
|
|
{
|
2009-04-13 02:57:32 -04:00
|
|
|
*Result = StackTop->p.Val;
|
2009-04-15 06:47:51 -04:00
|
|
|
HeapPopStack(StackTop, sizeof(struct ExpressionStack));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HeapPopStack(StackTop->p.Val, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StackTop->p.Val));
|
2009-03-29 07:08:03 -04:00
|
|
|
}
|
2009-03-28 07:10:34 -04:00
|
|
|
|
2009-04-13 02:57:32 -04:00
|
|
|
debugf("ExpressionParse() done\n");
|
2009-04-15 06:47:51 -04:00
|
|
|
#ifdef DEBUG_EXPRESSIONS
|
|
|
|
ExpressionStackShow(StackTop);
|
|
|
|
#endif
|
2009-04-13 05:02:45 -04:00
|
|
|
return StackTop != NULL;
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* do a function call */
|
2009-04-04 22:24:00 -04:00
|
|
|
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName)
|
2009-03-08 03:56:28 -04:00
|
|
|
{
|
2009-04-18 21:15:01 -04:00
|
|
|
struct Value *ReturnValue = NULL;
|
2009-03-08 03:56:28 -04:00
|
|
|
struct Value *FuncValue;
|
|
|
|
struct Value *Param;
|
2009-04-03 23:11:12 -04:00
|
|
|
struct Value **ParamArray = NULL;
|
2009-03-08 03:56:28 -04:00
|
|
|
int ArgCount;
|
|
|
|
enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
|
|
|
|
|
|
|
if (Parser->Mode == RunModeRun)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* get the function definition */
|
2009-03-08 03:56:28 -04:00
|
|
|
VariableGet(Parser, FuncName, &FuncValue);
|
|
|
|
if (FuncValue->Typ->Base != TypeFunction)
|
|
|
|
ProgramFail(Parser, "not a function - can't call");
|
|
|
|
|
2009-04-04 22:24:00 -04:00
|
|
|
ExpressionStackPushValueByType(Parser, StackTop, FuncValue->Val->FuncDef.ReturnType);
|
2009-04-13 02:57:32 -04:00
|
|
|
ReturnValue = (*StackTop)->p.Val;
|
2009-03-08 03:56:28 -04:00
|
|
|
HeapPushStackFrame();
|
|
|
|
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
|
|
|
if (ParamArray == NULL)
|
|
|
|
ProgramFail(Parser, "out of memory");
|
|
|
|
}
|
2009-04-15 06:47:51 -04:00
|
|
|
else
|
|
|
|
ExpressionPushInt(Parser, StackTop, 0);
|
2009-03-08 03:56:28 -04:00
|
|
|
|
|
|
|
/* 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)
|
2009-04-22 08:06:58 -04:00
|
|
|
{
|
2009-04-23 18:46:32 -04:00
|
|
|
/* parameter is the wrong type - can we coerce it to being the type we want? */
|
|
|
|
if (FuncValue->Val->FuncDef.ParamType[ArgCount] == &IntType && IS_INTEGER_COERCIBLE(Param))
|
|
|
|
Param->Val->Integer = COERCE_INTEGER(Param); /* cast to int */
|
|
|
|
|
|
|
|
else if (FuncValue->Val->FuncDef.ParamType[ArgCount] == &CharType && IS_INTEGER_COERCIBLE(Param))
|
|
|
|
Param->Val->Character = COERCE_INTEGER(Param); /* cast to char */
|
|
|
|
|
2009-04-22 08:06:58 -04:00
|
|
|
else
|
|
|
|
ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount+1, FuncName);
|
|
|
|
}
|
2009-03-08 03:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* end of argument list? */
|
2009-03-08 03:56:28 -04:00
|
|
|
Token = LexGetToken(Parser, NULL, TRUE);
|
|
|
|
if (!TokenCloseBracket)
|
|
|
|
ProgramFail(Parser, "bad argument");
|
|
|
|
}
|
|
|
|
} while (Token != TokenCloseBracket);
|
|
|
|
|
|
|
|
if (Parser->Mode == RunModeRun)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* run the function */
|
2009-03-08 03:56:28 -04:00
|
|
|
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
|
|
|
ProgramFail(Parser, "not enough arguments to '%s'", FuncName);
|
|
|
|
|
|
|
|
if (FuncValue->Val->FuncDef.Intrinsic == NULL)
|
2009-04-14 02:55:00 -04:00
|
|
|
{
|
|
|
|
/* run a user-defined function */
|
2009-03-08 03:56:28 -04:00
|
|
|
struct ParseState FuncParser = FuncValue->Val->FuncDef.Body;
|
|
|
|
int Count;
|
|
|
|
|
|
|
|
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
|
|
|
TopStackFrame->NumParams = ArgCount;
|
2009-04-04 22:24:00 -04:00
|
|
|
TopStackFrame->ReturnValue = ReturnValue;
|
2009-03-08 03:56:28 -04:00
|
|
|
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");
|
|
|
|
|
2009-04-04 22:24:00 -04:00
|
|
|
if (FuncValue->Val->FuncDef.ReturnType != ReturnValue->Typ)
|
2009-03-08 03:56:28 -04:00
|
|
|
ProgramFail(&FuncParser, "bad type of return value");
|
|
|
|
|
|
|
|
VariableStackFramePop(Parser);
|
|
|
|
}
|
|
|
|
else
|
2009-04-04 22:24:00 -04:00
|
|
|
FuncValue->Val->FuncDef.Intrinsic(Parser, ReturnValue, ParamArray, ArgCount);
|
2009-03-08 03:56:28 -04:00
|
|
|
|
|
|
|
HeapPopStackFrame();
|
|
|
|
}
|
|
|
|
}
|
2009-04-04 22:24:00 -04:00
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2009-04-22 08:06:58 -04:00
|
|
|
if (!IS_INTEGER_COERCIBLE(Val))
|
2009-04-04 22:24:00 -04:00
|
|
|
ProgramFail(Parser, "integer value expected");
|
|
|
|
|
2009-04-22 08:06:58 -04:00
|
|
|
Result = COERCE_INTEGER(Val);
|
2009-04-04 22:24:00 -04:00
|
|
|
VariableStackPop(Parser, Val);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|