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:
parent
d2da61b81d
commit
825c393240
2
Makefile
2
Makefile
|
@ -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
|
||||
|
|
151
expression.c
151
expression.c
|
@ -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
15
heap.c
|
@ -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
21
parse.c
|
@ -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;
|
||||
}
|
||||
|
|
6
picoc.h
6
picoc.h
|
@ -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
2
type.c
|
@ -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)
|
||||
|
|
21
variable.c
21
variable.c
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue