Reworking of how assignment works. Now all places which do assignment of values

should work the same.


git-svn-id: http://picoc.googlecode.com/svn/trunk@314 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-06-02 05:51:51 +00:00
parent d2da61b81d
commit 825c393240
7 changed files with 131 additions and 89 deletions

View file

@ -1,5 +1,5 @@
CC=gcc
CFLAGS=-Wall -g -DUNIX_HOST #-DDEBUG_EXPRESSIONS #-DDEBUG_LEXER
CFLAGS=-Wall -g -DUNIX_HOST #-DDEBUG_HEAP #-DDEBUG_EXPRESSIONS #-DDEBUG_LEXER
LIBS=#-lm
TARGET = picoc

View file

@ -169,7 +169,7 @@ void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionSt
struct Value *ExpressionStackPushValueByType(struct ParseState *Parser, struct ExpressionStack **StackTop, struct ValueType *PushType)
{
debugf("ExpressionStackPushValueByType()\n");
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL);
struct Value *ValueLoc = VariableAllocValueFromType(Parser, PushType, FALSE, NULL, FALSE);
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
return ValueLoc;
@ -204,7 +204,7 @@ void ExpressionStackPushDereference(struct ParseState *Parser, struct Expression
void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **StackTop, int IntValue)
{
debugf("ExpressionPushInt()\n");
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL, FALSE);
ValueLoc->Val->Integer = IntValue;
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
}
@ -213,17 +213,16 @@ void ExpressionPushInt(struct ParseState *Parser, struct ExpressionStack **Stack
void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackTop, double FPValue)
{
debugf("ExpressionPushFP()\n");
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL);
struct Value *ValueLoc = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL, FALSE);
ValueLoc->Val->FP = FPValue;
ExpressionStackPushValueNode(Parser, StackTop, ValueLoc);
}
#endif
/* assign to a pointer, leaving a value on the expression stack */
struct Value *ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue, struct Value *FromValue, int MakeValue)
void ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue, struct Value *FromValue)
{
struct ValueType *PointedToType = ToValue->Typ->FromType;
struct Value *ValueLoc = NULL;
struct Value *DerefVal = NULL;
int DerefOffset;
@ -260,21 +259,75 @@ struct Value *ExpressionAssignToPointer(struct ParseState *Parser, struct Value
ToValue->Val->NativePointer = DerefVal;
#endif
}
else
ProgramFail(Parser, "can't assign from a %t to a %t", FromValue->Typ, ToValue->Typ);
if (MakeValue)
else if (IS_NUMERIC_COERCIBLE(FromValue) && COERCE_INTEGER(FromValue) == 0)
{
/* put a copy of the pointer on the stack */
ValueLoc = VariableAllocValueFromType(Parser, ToValue->Typ, TRUE, NULL);
/* null pointer assignment */
#ifndef NATIVE_POINTERS
ValueLoc->Val->Pointer = ToValue->Val->Pointer;
ToValue->Val->Pointer.Segment = NULL;
ToValue->Val->Pointer.Offset = 0;
#else
ValueLoc->Val->NativePointer = ToValue->Val->NativePointer;
ToValue->Val->NativePointer = NULL;
#endif
}
else
ProgramFail(Parser, "can't assign from a %t to a %t", FromValue->Typ, ToValue->Typ);
}
return ValueLoc;
/* assign any kind of value */
void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct Value *SourceValue, int Force)
{
if (!DestValue->IsLValue && !Force)
ProgramFail(Parser, "can't assign to this");
switch (DestValue->Typ->Base)
{
case TypeInt:
if (!IS_NUMERIC_COERCIBLE(SourceValue))
ProgramFail(Parser, "can't assign to this");
DestValue->Val->Integer = COERCE_INTEGER(SourceValue);
break;
case TypeChar:
if (!IS_NUMERIC_COERCIBLE(SourceValue))
ProgramFail(Parser, "can't assign to this");
DestValue->Val->Character = COERCE_INTEGER(SourceValue);
break;
#ifndef NO_FP
case TypeFP:
if (!IS_NUMERIC_COERCIBLE(SourceValue))
ProgramFail(Parser, "can't assign to this");
DestValue->Val->FP = COERCE_FP(SourceValue);
break;
#endif
case TypePointer:
ExpressionAssignToPointer(Parser, DestValue, SourceValue);
break;
case TypeArray:
if (DestValue->Typ != SourceValue->Typ)
ProgramFail(Parser, "can't assign from a %t to a %t", SourceValue->Typ, DestValue->Typ);
if (DestValue->Val->Array.Size != SourceValue->Val->Array.Size)
ProgramFail(Parser, "can't assign from an array of size %d to one of size %d", SourceValue->Val->Array.Size, DestValue->Val->Array.Size);
memcpy((void *)DestValue->Val->Array.Data, (void *)SourceValue->Val->Array.Data, DestValue->Val->Array.Size);
break;
case TypeStruct:
case TypeUnion:
if (DestValue->Typ != SourceValue->Typ)
ProgramFail(Parser, "can't assign from a %t to a %t", SourceValue->Typ, DestValue->Typ);
memcpy((void *)DestValue->Val, (void *)SourceValue->Val, TypeSizeValue(SourceValue));
break;
default:
ProgramFail(Parser, "can't assign to a %t", DestValue->Typ);
break;
}
}
/* evaluate a prefix operator */
@ -299,7 +352,7 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
TempLValue = TopValue->LValueFrom;
assert(TempLValue != NULL);
Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, TopValue->Typ, TypePointer, 0, StrEmpty), FALSE, NULL);
Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, TopValue->Typ, TypePointer, 0, StrEmpty), FALSE, NULL, FALSE);
#ifndef NATIVE_POINTERS
Result->Val->Pointer.Segment = TempLValue;
if (Result->LValueFrom != NULL)
@ -528,7 +581,6 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
ProgramFail(Parser, "illegal array index %d [0..%d]", ArrayIndex, BottomValue->Val->Array.Size-1);
/* make the array element result */
// XXX - need to handle char array access
Result = VariableAllocValueFromExistingData(Parser, BottomValue->Typ->FromType, (union AnyValue *)(BottomValue->Val->Array.Data + TypeSize(BottomValue->Typ->FromType, 0, FALSE) * ArrayIndex), BottomValue->IsLValue, BottomValue->LValueFrom);
ExpressionStackPushValueNode(Parser, StackTop, Result);
}
@ -677,10 +729,9 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
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);
HeapUnpopStack(sizeof(struct Value)); // XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value)
ExpressionAssign(Parser, BottomValue, TopValue, FALSE);
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
}
else
ProgramFail(Parser, "invalid operation");
@ -707,20 +758,9 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
else if (Op == TokenAssign)
{
/* assign a non-numeric type */
if (!BottomValue->IsLValue)
ProgramFail(Parser, "can't assign to this");
if (BottomValue->Typ->Base == TypePointer)
ExpressionStackPushValueNode(Parser, StackTop, ExpressionAssignToPointer(Parser, BottomValue, TopValue, TRUE)); /* pointer assignment */
else
{
/* assign anything else */
if (BottomValue->Typ != TopValue->Typ)
ProgramFail(Parser, "can't assign from a %t to a %t", TopValue->Typ, BottomValue->Typ);
memcpy((void *)BottomValue->Val, (void *)TopValue->Val, TypeSizeValue(TopValue)); // XXX - need to handle arrays
ExpressionStackPushValue(Parser, StackTop, TopValue);
}
HeapUnpopStack(sizeof(struct Value)); // XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value)
ExpressionAssign(Parser, BottomValue, TopValue, FALSE);
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
}
else
ProgramFail(Parser, "invalid operation");
@ -1043,7 +1083,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
HeapPopStack(StackTop->p.Val, sizeof(struct ExpressionStack) + sizeof(struct Value) + TypeStackSizeValue(StackTop->p.Val));
}
debugf("ExpressionParse() done\n");
debugf("ExpressionParse() done\n\n");
#ifdef DEBUG_EXPRESSIONS
ExpressionStackShow(StackTop);
#endif
@ -1081,44 +1121,22 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
/* parse arguments */
ArgCount = 0;
do {
if (Parser->Mode == RunModeRun && ArgCount < FuncValue->Val->FuncDef.NumParams)
ParamArray[ArgCount] = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ParamType[ArgCount], FALSE, NULL, FALSE);
if (ExpressionParse(Parser, &Param))
{
if (Parser->Mode == RunModeRun)
{
if (ArgCount >= FuncValue->Val->FuncDef.NumParams)
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
{
if (!FuncValue->Val->FuncDef.VarArgs)
ProgramFail(Parser, "too many arguments to %s()", FuncName);
ExpressionAssign(Parser, ParamArray[ArgCount], Param, TRUE);
VariableStackPop(Parser, Param);
}
else
{
if (FuncValue->Val->FuncDef.ParamType[ArgCount] != Param->Typ)
{
/* parameter is the wrong type - can we coerce it to being the type we want? */
if (IS_NUMERIC_COERCIBLE(Param))
{
int IntVal = COERCE_INTEGER(Param); /* cast to int */
#ifndef NO_FP
double FloatVal = COERCE_FP(Param); /* cast to float */
#endif
VariableStackPop(Parser, Param);
Param = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ParamType[ArgCount], FALSE, NULL);
if (FuncValue->Val->FuncDef.ParamType[ArgCount] == &IntType)
Param->Val->Integer = IntVal;
else if (FuncValue->Val->FuncDef.ParamType[ArgCount] == &CharType)
Param->Val->Character = IntVal;
#ifndef NO_FP
else
Param->Val->FP = FloatVal;
#endif
}
else
ProgramFail(Parser, "parameter %d to %s() is %t instead of %t", ArgCount+1, FuncName, Param->Typ, FuncValue->Val->FuncDef.ParamType[ArgCount]);
}
ParamArray[ArgCount] = Param;
if (!FuncValue->Val->FuncDef.VarArgs)
ProgramFail(Parser, "too many arguments to %s()", FuncName);
}
}
@ -1134,6 +1152,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
if (!TokenCloseBracket)
ProgramFail(Parser, "bad argument");
}
} while (Token != TokenCloseBracket);
if (Parser->Mode == RunModeRun)
@ -1152,7 +1171,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
TopStackFrame->NumParams = ArgCount;
TopStackFrame->ReturnValue = ReturnValue;
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], TRUE);
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE);
if (!ParseStatement(&FuncParser))
ProgramFail(&FuncParser, "function body expected");

15
heap.c
View file

@ -55,6 +55,9 @@ void *HeapAllocStack(int Size)
{
void *NewMem = HeapStackTop;
void *NewTop = HeapStackTop + MEM_ALIGN(Size);
#ifdef DEBUG_HEAP
printf("HeapAllocStack(%d) at 0x%lx\n", MEM_ALIGN(Size), (unsigned long)HeapStackTop);
#endif
if (NewTop > HeapBottom)
return NULL;
@ -63,6 +66,15 @@ void *HeapAllocStack(int Size)
return NewMem;
}
/* allocate some space on the stack, in the current stack frame */
void HeapUnpopStack(int Size)
{
#ifdef DEBUG_HEAP
printf("HeapUnpopStack(%d) at 0x%lx\n", MEM_ALIGN(Size), (unsigned long)HeapStackTop);
#endif
HeapStackTop = HeapStackTop + MEM_ALIGN(Size);
}
/* free some space at the top of the stack */
int HeapPopStack(void *Addr, int Size)
{
@ -70,6 +82,9 @@ int HeapPopStack(void *Addr, int Size)
if (ToLose > (HeapStackTop - (void *)&HeapMemory[0]))
return FALSE;
#ifdef DEBUG_HEAP
printf("HeapPopStack(0x%lx, %d) back to 0x%lx\n", (unsigned long)Addr, MEM_ALIGN(Size), (unsigned long)HeapStackTop - ToLose);
#endif
HeapStackTop -= ToLose;
assert(HeapStackTop == Addr);

21
parse.c
View file

@ -105,6 +105,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
struct ValueType *BasicType;
struct ValueType *Typ;
struct Value *CValue;
struct Value *NewVariable;
TypeParseFront(Parser, &BasicType);
do
@ -126,17 +127,20 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
if (Token == TokenVoidType && Identifier != StrEmpty)
ProgramFail(Parser, "can't define a void variable");
if (LexGetToken(Parser, NULL, FALSE) != TokenAssign)
VariableDefine(Parser, Identifier, VariableAllocValueFromType(Parser, Typ, TRUE, NULL), TRUE);
else
{ /* we're assigning an initial value */
NewVariable = VariableDefine(Parser, Identifier, NULL, Typ, TRUE);
if (LexGetToken(Parser, NULL, FALSE) == TokenAssign)
{
/* we're assigning an initial value */
LexGetToken(Parser, NULL, TRUE);
if (!ExpressionParse(Parser, &CValue))
ProgramFail(Parser, "expression expected");
VariableDefine(Parser, Identifier, CValue, TRUE);
if (Parser->Mode == RunModeRun)
{
ExpressionAssign(Parser, NewVariable, CValue, FALSE);
VariableStackPop(Parser, CValue);
}
}
}
}
@ -463,12 +467,7 @@ int ParseStatement(struct ParseState *Parser)
if (!ExpressionParse(Parser, &CValue) && TopStackFrame->ReturnValue->Typ->Base != TypeVoid)
ProgramFail(Parser, "value required in return");
if (CValue->Typ != TopStackFrame->ReturnValue->Typ)
ProgramFail(Parser, "wrong return type");
// XXX - make assignment a separate function
// XXX - also arrays need cleverer assignment
memcpy((void *)TopStackFrame->ReturnValue->Val, (void *)CValue->Val, TypeSizeValue(CValue));
ExpressionAssign(Parser, TopStackFrame->ReturnValue, CValue, TRUE);
VariableStackPop(Parser, CValue);
Parser->Mode = RunModeReturn;
}

View file

@ -317,6 +317,7 @@ void ParserCopyPos(struct ParseState *To, struct ParseState *From);
/* expression.c */
int ExpressionParse(struct ParseState *Parser, struct Value **Result);
int ExpressionParseInt(struct ParseState *Parser);
void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct Value *SourceValue, int Force);
/* type.c */
void TypeInit();
@ -334,6 +335,7 @@ struct ValueType *TypeGetMatching(struct ParseState *Parser, struct ValueType *P
void HeapInit();
void *HeapAllocStack(int Size);
int HeapPopStack(void *Addr, int Size);
void HeapUnpopStack(int Size);
void HeapPushStackFrame();
int HeapPopStackFrame();
void *HeapAlloc(int Size);
@ -348,10 +350,10 @@ void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap);
void VariableStackPop(struct ParseState *Parser, struct Value *Var);
struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, int IsLValue, struct Value *LValueFrom, int OnHeap);
struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap);
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom);
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap);
struct Value *VariableAllocValueFromExistingData(struct ParseState *Parser, struct ValueType *Typ, union AnyValue *FromValue, int IsLValue, struct Value *LValueFrom);
struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *FromValue);
void VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, int MakeWritable);
struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable);
int VariableDefined(const char *Ident);
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal);
void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable);

2
type.c
View file

@ -270,7 +270,7 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
EnumValue = ExpressionParseInt(Parser);
}
VariableDefine(Parser, EnumIdentifier, &InitValue, FALSE);
VariableDefine(Parser, EnumIdentifier, &InitValue, NULL, FALSE);
Token = LexGetToken(Parser, NULL, TRUE);
if (Token != TokenComma && Token != TokenRightBrace)

View file

@ -99,16 +99,16 @@ struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize,
}
/* allocate a value given its type */
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom)
struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int IsLValue, struct Value *LValueFrom, int OnHeap)
{
int Size = TypeSize(Typ, Typ->ArraySize, FALSE);
struct Value *NewValue = VariableAllocValueAndData(Parser, Size, IsLValue, LValueFrom, FALSE);
struct Value *NewValue = VariableAllocValueAndData(Parser, Size, IsLValue, LValueFrom, OnHeap);
assert(Size > 0 || Typ == &VoidType);
NewValue->Typ = Typ;
if (Typ->Base == TypeArray)
{
NewValue->Val->Array.Size = Typ->ArraySize;
NewValue->Val->Array.Data = (void *)NewValue->Val;
NewValue->Val->Array.Data = (void *)NewValue->Val + sizeof(struct ArrayValue);
}
return NewValue;
@ -121,6 +121,7 @@ struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value
struct Value *NewValue = VariableAllocValueAndData(Parser, CopySize, FromValue->IsLValue, FromValue->LValueFrom, OnHeap);
NewValue->Typ = FromValue->Typ;
memcpy((void *)NewValue->Val, (void *)FromValue->Val, CopySize);
return NewValue;
}
@ -145,15 +146,21 @@ struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *
}
/* define a variable. Ident must be registered */
void VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, int MakeWritable)
struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable)
{
struct Value *AssignValue = VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL);
struct Value *AssignValue;
if (MakeWritable)
AssignValue->IsLValue = TRUE;
if (InitValue != NULL)
AssignValue = VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL);
else
AssignValue = VariableAllocValueFromType(Parser, Typ, MakeWritable, NULL, TopStackFrame == NULL);
AssignValue->IsLValue = MakeWritable;
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue))
ProgramFail(Parser, "'%s' is already defined", Ident);
return AssignValue;
}
/* check if a variable with a given name is defined. Ident must be registered */