Structs now work in the new expression system.

Tests 03 and 04 now pass.


git-svn-id: http://picoc.googlecode.com/svn/trunk@230 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-04-14 03:18:40 +00:00
parent 9e24449497
commit d034ded5fc

View file

@ -11,8 +11,10 @@
#define COERCE_INTEGER(v) ((v)->Val->Integer)
#endif
/* helper macros for assignment */
#define ASSIGN_INT(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultInt = (s); (d)->Val->Integer = ResultInt; }
#define ASSIGN_INT_AFTER(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultInt = (d)->Val->Integer; (d)->Val->Integer = (s); }
#define ASSIGN_FP(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultFP = (s); (d)->Val->FP = ResultFP; }
#define BRACKET_PRECEDENCE 20
@ -592,6 +594,7 @@ void ExpressionStackShow(struct ExpressionStack *StackTop)
switch (StackTop->p.Val->Typ->Base)
{
case TypeVoid: printf("void"); break;
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;
@ -809,121 +812,112 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
}
debugf("ExpressionInfixOperator()\n");
switch (Op)
if (IS_INTEGER_COERCIBLE(TopValue) && IS_INTEGER_COERCIBLE(BottomValue))
{
case TokenComma:
case TokenAssign:
case TokenDot:
case TokenArrow:
default:
if (IS_INTEGER_COERCIBLE(TopValue) && IS_INTEGER_COERCIBLE(BottomValue))
{
int TopInt = COERCE_INTEGER(TopValue);
int BottomInt = COERCE_INTEGER(BottomValue);
switch (Op)
{
case TokenAssign: ASSIGN_INT(BottomValue, TopInt); break;
case TokenAddAssign: ASSIGN_INT(BottomValue, BottomInt + TopInt); break;
case TokenSubtractAssign: ASSIGN_INT(BottomValue, BottomInt - TopInt); break;
case TokenMultiplyAssign: ASSIGN_INT(BottomValue, BottomInt * TopInt); break;
case TokenDivideAssign: ASSIGN_INT(BottomValue, BottomInt / TopInt); break;
case TokenModulusAssign: ASSIGN_INT(BottomValue, BottomInt % TopInt); break;
case TokenShiftLeftAssign: ASSIGN_INT(BottomValue, BottomInt << TopInt); break;
case TokenShiftRightAssign: ASSIGN_INT(BottomValue, BottomInt >> TopInt); break;
case TokenArithmeticAndAssign: ASSIGN_INT(BottomValue, BottomInt & TopInt); break;
case TokenArithmeticOrAssign: ASSIGN_INT(BottomValue, BottomInt | TopInt); break;
case TokenArithmeticExorAssign: ASSIGN_INT(BottomValue, BottomInt ^ TopInt); break;
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;
case TokenModulus: ResultInt = BottomInt % TopInt; break;
default: ProgramFail(Parser, "invalid operation"); break;
}
int TopInt = COERCE_INTEGER(TopValue);
int BottomInt = COERCE_INTEGER(BottomValue);
switch (Op)
{
case TokenAssign: ASSIGN_INT(BottomValue, TopInt); break;
case TokenAddAssign: ASSIGN_INT(BottomValue, BottomInt + TopInt); break;
case TokenSubtractAssign: ASSIGN_INT(BottomValue, BottomInt - TopInt); break;
case TokenMultiplyAssign: ASSIGN_INT(BottomValue, BottomInt * TopInt); break;
case TokenDivideAssign: ASSIGN_INT(BottomValue, BottomInt / TopInt); break;
case TokenModulusAssign: ASSIGN_INT(BottomValue, BottomInt % TopInt); break;
case TokenShiftLeftAssign: ASSIGN_INT(BottomValue, BottomInt << TopInt); break;
case TokenShiftRightAssign: ASSIGN_INT(BottomValue, BottomInt >> TopInt); break;
case TokenArithmeticAndAssign: ASSIGN_INT(BottomValue, BottomInt & TopInt); break;
case TokenArithmeticOrAssign: ASSIGN_INT(BottomValue, BottomInt | TopInt); break;
case TokenArithmeticExorAssign: ASSIGN_INT(BottomValue, BottomInt ^ TopInt); break;
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;
case TokenModulus: ResultInt = BottomInt % TopInt; break;
default: ProgramFail(Parser, "invalid operation"); break;
}
ExpressionPushInt(Parser, StackTop, ResultInt);
}
ExpressionPushInt(Parser, StackTop, ResultInt);
}
#ifndef NO_FP
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 */
double ResultFP;
double TopFP = (TopValue->Typ == &FPType) ? TopValue->Val->FP : (double)COERCE_INTEGER(TopValue);
double BottomFP = (BottomValue->Typ == &FPType) ? BottomValue->Val->FP : (double)COERCE_INTEGER(BottomValue);
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 */
double ResultFP;
double TopFP = (TopValue->Typ == &FPType) ? TopValue->Val->FP : (double)COERCE_INTEGER(TopValue);
double BottomFP = (BottomValue->Typ == &FPType) ? BottomValue->Val->FP : (double)COERCE_INTEGER(BottomValue);
switch (Op)
{
case TokenAddAssign: break; // XXX
case TokenSubtractAssign: break; // XXX
case TokenMultiplyAssign: break; // XXX
case TokenDivideAssign: break; // XXX
case TokenModulusAssign: break; // XXX
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;
}
switch (Op)
{
case TokenAssign: ASSIGN_FP(BottomValue, TopFP); break;
case TokenAddAssign: ASSIGN_FP(BottomValue, BottomFP + TopFP); break;
case TokenSubtractAssign: ASSIGN_FP(BottomValue, BottomFP - TopFP); break;
case TokenMultiplyAssign: ASSIGN_FP(BottomValue, BottomFP * TopFP); break;
case TokenDivideAssign: ASSIGN_FP(BottomValue, BottomFP / TopFP); break;
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;
}
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
else
ExpressionPushFP(Parser, StackTop, ResultFP);
}
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
else
ExpressionPushFP(Parser, StackTop, ResultFP);
}
#endif
#if 0
XXX - finish this
else if ( (TopValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(BottomValue)) ||
(IS_INTEGER_COERCIBLE(TopValue) && BottomValue->Typ->Base == TypePointer) )
{
/* pointer infix arithmetic */
else if ( (TopValue->Typ->Base == TypePointer && IS_INTEGER_COERCIBLE(BottomValue)) ||
(IS_INTEGER_COERCIBLE(TopValue) && BottomValue->Typ->Base == TypePointer) )
{
/* pointer infix arithmetic */
switch (TopOperatorNode->Op)
{
case TokenEqual: ResultInt = BottomInt == TopInt; ResultIsInt = TRUE; break;
case TokenNotEqual: ResultInt = BottomInt != TopInt; ResultIsInt = TRUE; break;
case TokenLessThan: ResultInt = BottomInt < TopInt; ResultIsInt = TRUE; break;
case TokenGreaterThan: ResultInt = BottomInt > TopInt; ResultIsInt = TRUE; break;
case TokenLessEqual: ResultInt = BottomInt <= TopInt; ResultIsInt = TRUE; break;
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; ResultIsInt = TRUE; break;
case TokenPlus: Result = BottomInt + TopInt; break;
case TokenMinus: Result = BottomInt - TopInt; break;
default: ProgramFail(Parser, "invalid operation"); break;
}
switch (TopOperatorNode->Op)
{
case TokenEqual: ResultInt = BottomInt == TopInt; ResultIsInt = TRUE; break;
case TokenNotEqual: ResultInt = BottomInt != TopInt; ResultIsInt = TRUE; break;
case TokenLessThan: ResultInt = BottomInt < TopInt; ResultIsInt = TRUE; break;
case TokenGreaterThan: ResultInt = BottomInt > TopInt; ResultIsInt = TRUE; break;
case TokenLessEqual: ResultInt = BottomInt <= TopInt; ResultIsInt = TRUE; break;
case TokenGreaterEqual: ResultInt = BottomInt >= TopInt; ResultIsInt = TRUE; break;
case TokenPlus: Result = BottomInt + TopInt; break;
case TokenMinus: Result = BottomInt - TopInt; break;
default: ProgramFail(Parser, "invalid operation"); break;
}
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
else
ExpressionPushPointer(Parser, StackTop, ResultInt);
}
#endif
else
ProgramFail(Parser, "invalid operation"); break;
break;
if (ResultIsInt)
ExpressionPushInt(Parser, StackTop, ResultInt);
else
ExpressionPushPointer(Parser, StackTop, ResultInt);
}
#endif
else
ProgramFail(Parser, "invalid operation");
}
/* take the contents of the expression stack and compute the top until there's nothing greater than the given precedence */
@ -1022,6 +1016,40 @@ void ExpressionStackPushOperator(struct ParseState *Parser, struct ExpressionSta
#endif
}
/* 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)
{ /* look up the struct element */
struct Value *StructVal = (*StackTop)->p.Val;
struct Value *MemberValue;
struct Value *Result;
if (Token == TokenArrow)
ProgramFail(Parser, "'->' not implemented yet");
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 */
HeapPopStack(StructVal, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StructVal));
*StackTop = (*StackTop)->Next;
/* make the result value for this member only */
Result = VariableAllocValueFromExistingData(Parser, MemberValue->Typ, (void *)StructVal->Val + MemberValue->Val->Integer, TRUE, StructVal->LValueFrom);
ExpressionStackPushValueNode(Parser, StackTop, Result);
}
}
/* parse an expression with operator precedence */
int ExpressionParse(struct ParseState *Parser, struct Value **Result)
{
@ -1096,17 +1124,22 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
}
else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0)
{ /* scan and collapse the stack, then push */
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);
if (Token == TokenDot || Token == TokenArrow)
ExpressionGetStructElement(Parser, &StackTop, Token); /* this operator is followed by a struct element so handle it as a special case */
else
ExpressionStackCollapse(Parser, &StackTop, Precedence+1);
{ /* a standard infix operator */
Precedence = BracketPrecedence + OperatorPrecedence[(int)Token].InfixPrecedence;
ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, Token, Precedence);
PrefixState = TRUE;
/* 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);
ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, Token, Precedence);
PrefixState = TRUE;
}
}
else
ProgramFail(Parser, "operator not expected here");