Fixed a problem with variable declarations in inner blocks giving errors. bug#82.

git-svn-id: http://picoc.googlecode.com/svn/trunk@470 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2010-07-24 16:07:56 +00:00
parent d87d25fede
commit 036f3efa8b
10 changed files with 63 additions and 24 deletions

View file

@ -767,7 +767,7 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
else if (Op == TokenAssign && TopInt == 0)
{
/* assign a NULL pointer */
HeapUnpopStack(sizeof(struct Value)); /* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */
HeapUnpopStack(sizeof(struct Value));
ExpressionAssign(Parser, BottomValue, TopValue, FALSE, NULL, 0, FALSE);
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
}
@ -785,7 +785,7 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
else
Pointer = (void *)((char *)Pointer - TopInt * Size);
HeapUnpopStack(sizeof(struct Value)); /* XXX - possible bug if lvalue is a temp value and takes more than sizeof(struct Value) */
HeapUnpopStack(sizeof(struct Value));
BottomValue->Val->Pointer = Pointer;
ExpressionStackPushValueNode(Parser, StackTop, BottomValue);
}
@ -963,7 +963,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
if (StructType->Base != TypeStruct && StructType->Base != TypeUnion)
ProgramFail(Parser, "can't use '%s' on something that's not a struct or union %s : it's a %t", (Token == TokenDot) ? "." : "->", (Token == TokenArrow) ? "pointer" : "", ParamVal->Typ);
if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue))
if (!TableGet(StructType->Members, Ident->Val->Identifier, &MemberValue, NULL, NULL))
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 */

4
lex.c
View file

@ -755,7 +755,7 @@ void LexHashIfdef(struct ParseState *Parser, int IfNot)
ProgramFail(Parser, "identifier expected");
/* is the identifier defined? */
IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue);
IsDefined = TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL);
if (Parser->HashIfEvaluateToLevel == Parser->HashIfLevel && ( (IsDefined && !IfNot) || (!IsDefined && IfNot)) )
{
/* #if is active, evaluate to this new level */
@ -777,7 +777,7 @@ void LexHashIf(struct ParseState *Parser)
if (Token == TokenIdentifier)
{
/* look up a value from a macro definition */
if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue))
if (!TableGet(&GlobalTable, IdentValue->Val->Identifier, &SavedValue, NULL, NULL))
ProgramFail(Parser, "'%s' is undefined", IdentValue->Val->Identifier);
if (SavedValue->Typ->Base != TypeMacro)

View file

@ -128,7 +128,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp
FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser);
/* is this function already in the global table? */
if (TableGet(&GlobalTable, Identifier, &OldFuncValue))
if (TableGet(&GlobalTable, Identifier, &OldFuncValue, NULL, NULL))
{
if (OldFuncValue->Val->FuncDef.Body.Pos == NULL)
TableDelete(&GlobalTable, Identifier); /* override an old function prototype */
@ -137,7 +137,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp
}
}
if (!TableSet(&GlobalTable, Identifier, FuncValue))
if (!TableSet(&GlobalTable, Identifier, FuncValue, Parser->Line, Parser->CharacterPos))
ProgramFail(Parser, "'%s' is already defined", Identifier);
return FuncValue;
@ -227,7 +227,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
ProgramFail(Parser, "can't define a void variable");
if (Parser->Mode == RunModeRun)
NewVariable = VariableDefine(Parser, Identifier, NULL, Typ, TRUE);
NewVariable = VariableDefineButIgnoreIdentical(Parser, Identifier, Typ);
if (LexGetToken(Parser, NULL, FALSE) == TokenAssign)
{
@ -304,7 +304,7 @@ void ParseMacroDefinition(struct ParseState *Parser)
LexToEndOfLine(Parser);
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
if (!TableSet(&GlobalTable, MacroNameStr, MacroValue))
if (!TableSet(&GlobalTable, MacroNameStr, MacroValue, Parser->Line, Parser->CharacterPos))
ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
}

View file

@ -208,6 +208,9 @@ struct Value
struct TableEntry
{
struct TableEntry *Next; /* next item in this hash chain */
unsigned short DeclLine; /* where the variable was declared */
unsigned short DeclColumn;
union TableEntryPayload
{
struct ValueEntry
@ -321,8 +324,8 @@ void TableInit();
char *TableStrRegister(const char *Str);
char *TableStrRegister2(const char *Str, int Len);
void TableInitTable(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap);
int TableSet(struct Table *Tbl, char *Key, struct Value *Val);
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val);
int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int DeclColumn);
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, int *DeclLine, int *DeclColumn);
struct Value *TableDelete(struct Table *Tbl, const char *Key);
char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen);
void TableStrFree();
@ -394,6 +397,7 @@ struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct Value
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);
struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable);
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ);
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);

15
table.c
View file

@ -56,7 +56,7 @@ static struct TableEntry *TableSearch(struct Table *Tbl, const char *Key, int *A
/* set an identifier to a value. returns FALSE if it already exists.
* Key must be a shared string from TableStrRegister() */
int TableSet(struct Table *Tbl, char *Key, struct Value *Val)
int TableSet(struct Table *Tbl, char *Key, struct Value *Val, int DeclLine, int DeclColumn)
{
int AddAt;
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
@ -64,6 +64,8 @@ int TableSet(struct Table *Tbl, char *Key, struct Value *Val)
if (FoundEntry == NULL)
{ /* add it to the table */
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
NewEntry->DeclLine = DeclLine;
NewEntry->DeclColumn = DeclColumn;
NewEntry->p.v.Key = Key;
NewEntry->p.v.Val = Val;
NewEntry->Next = Tbl->HashTable[AddAt];
@ -76,7 +78,7 @@ int TableSet(struct Table *Tbl, char *Key, struct Value *Val)
/* find a value in a table. returns FALSE if not found.
* Key must be a shared string from TableStrRegister() */
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val)
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val, int *DeclLine, int *DeclColumn)
{
int AddAt;
struct TableEntry *FoundEntry = TableSearch(Tbl, Key, &AddAt);
@ -84,6 +86,13 @@ int TableGet(struct Table *Tbl, const char *Key, struct Value **Val)
return FALSE;
*Val = FoundEntry->p.v.Val;
if (DeclLine != NULL)
{
*DeclLine = FoundEntry->DeclLine;
*DeclColumn = FoundEntry->DeclColumn;
}
return TRUE;
}
@ -132,7 +141,7 @@ char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen)
return &FoundEntry->p.Key[0];
else
{ /* add it to the table - we economise by not allocating the whole structure here */
struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry *) + IdentLen + 1);
struct TableEntry *NewEntry = HeapAllocMem(sizeof(struct TableEntry) - sizeof(union TableEntryPayload) + IdentLen + 1);
if (NewEntry == NULL)
ProgramFail(NULL, "out of memory");

View file

@ -0,0 +1,10 @@
#include <stdio.h>
int a;
for (a = 0; a < 2; a++)
{
int b = a;
}
printf("it's all good\n");

View file

@ -0,0 +1 @@
it's all good

View file

@ -38,7 +38,8 @@ TESTS= 00_assignment.test \
39_typedef.test \
40_stdio.test \
41_hashif.test \
43_void_param.test
43_void_param.test \
44_scoped_declarations.test
%.test: %.expect %.c
@echo Test: $*...

2
type.c
View file

@ -233,7 +233,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsSt
(*Typ)->Sizeof = TypeSizeValue(MemberValue);
}
if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue))
if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->Line, Parser->CharacterPos))
ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier);
if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon)

View file

@ -161,20 +161,34 @@ struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Valu
AssignValue->IsLValue = MakeWritable;
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue))
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
ProgramFail(Parser, "'%s' is already defined", Ident);
return AssignValue;
}
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ)
{
struct Value *ExistingValue;
int DeclLine;
int DeclColumn;
if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclLine, &DeclColumn)
&& DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos)
return ExistingValue;
else
return VariableDefine(Parser, Ident, NULL, Typ, TRUE);
}
/* check if a variable with a given name is defined. Ident must be registered */
int VariableDefined(const char *Ident)
{
struct Value *FoundValue;
if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, &FoundValue))
if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, &FoundValue, NULL, NULL))
{
if (!TableGet(&GlobalTable, Ident, &FoundValue))
if (!TableGet(&GlobalTable, Ident, &FoundValue, NULL, NULL))
return FALSE;
}
@ -184,9 +198,9 @@ int VariableDefined(const char *Ident)
/* get the value of a variable. must be defined. Ident must be registered */
void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal)
{
if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal))
if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal, NULL, NULL))
{
if (!TableGet(&GlobalTable, Ident, LVal))
if (!TableGet(&GlobalTable, Ident, LVal, NULL, NULL))
ProgramFail(Parser, "'%s' is undefined", Ident);
}
}
@ -198,7 +212,7 @@ void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct Va
SomeValue->Typ = Typ;
SomeValue->Val = FromValue;
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue))
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
ProgramFail(Parser, "'%s' is already defined", Ident);
}
@ -261,7 +275,7 @@ struct Value *VariableStringLiteralGet(char *Ident)
{
struct Value *LVal = NULL;
if (TableGet(&StringLiteralTable, Ident, &LVal))
if (TableGet(&StringLiteralTable, Ident, &LVal, NULL, NULL))
return LVal;
else
return NULL;
@ -270,7 +284,7 @@ struct Value *VariableStringLiteralGet(char *Ident)
/* define a string literal. assumes that Ident is already registered */
void VariableStringLiteralDefine(char *Ident, struct Value *Val)
{
TableSet(&StringLiteralTable, Ident, Val);
TableSet(&StringLiteralTable, Ident, Val, 0, 0);
}
/* check a pointer for validity and dereference it for use */