2009-01-23 06:34:12 -05:00
|
|
|
#include "picoc.h"
|
|
|
|
|
|
|
|
/* some basic types */
|
|
|
|
struct ValueType UberType;
|
|
|
|
struct ValueType IntType;
|
|
|
|
struct ValueType CharType;
|
|
|
|
struct ValueType StringType;
|
|
|
|
struct ValueType FPType;
|
|
|
|
struct ValueType VoidType;
|
|
|
|
struct ValueType FunctionType;
|
|
|
|
struct ValueType MacroType;
|
|
|
|
struct ValueType EnumType;
|
|
|
|
struct ValueType Type_Type;
|
|
|
|
|
|
|
|
|
|
|
|
/* add a new type to the set of types we know about */
|
|
|
|
struct ValueType *TypeAdd(struct LexState *Lexer, struct ValueType *ParentType, enum BaseType Base, int ArraySize, Str *Identifier, int Sizeof)
|
|
|
|
{
|
2009-01-23 22:15:02 -05:00
|
|
|
struct ValueType *NewType = VariableAlloc(Lexer, sizeof(struct ValueType));
|
2009-01-23 06:34:12 -05:00
|
|
|
NewType->Base = Base;
|
|
|
|
NewType->ArraySize = ArraySize;
|
|
|
|
NewType->Sizeof = Sizeof;
|
2009-01-24 21:09:44 -05:00
|
|
|
NewType->Identifier = *Identifier;
|
2009-01-23 06:34:12 -05:00
|
|
|
NewType->Members = NULL;
|
|
|
|
NewType->FromType = ParentType;
|
|
|
|
NewType->DerivedTypeList = NULL;
|
|
|
|
NewType->Next = ParentType->DerivedTypeList;
|
|
|
|
ParentType->DerivedTypeList = NewType;
|
|
|
|
|
|
|
|
return NewType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* given a parent type, get a matching derived type and make one if necessary */
|
|
|
|
struct ValueType *TypeGetMatching(struct LexState *Lexer, struct ValueType *ParentType, enum BaseType Base, int ArraySize, Str *Identifier)
|
|
|
|
{
|
|
|
|
int Sizeof;
|
|
|
|
struct ValueType *ThisType = ParentType->DerivedTypeList;
|
2009-01-23 22:15:02 -05:00
|
|
|
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || !StrEqual(&ThisType->Identifier, Identifier)))
|
2009-01-23 06:34:12 -05:00
|
|
|
ThisType = ThisType->Next;
|
|
|
|
|
|
|
|
if (ThisType != NULL)
|
|
|
|
return ThisType;
|
|
|
|
|
|
|
|
switch (Base)
|
|
|
|
{
|
|
|
|
case TypePointer: Sizeof = sizeof(struct PointerValue); break;
|
|
|
|
case TypeArray: Sizeof = ArraySize * ParentType->Sizeof; break;
|
|
|
|
case TypeEnum: Sizeof = sizeof(int); break;
|
|
|
|
default: Sizeof = 0; break; /* structs and unions will get bigger when we add members to them */
|
|
|
|
}
|
|
|
|
|
|
|
|
return TypeAdd(Lexer, ParentType, Base, ArraySize, Identifier, Sizeof);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add a base type */
|
|
|
|
void TypeAddBaseType(struct ValueType *TypeNode, enum BaseType Base, int Sizeof)
|
|
|
|
{
|
|
|
|
TypeNode->Base = Base;
|
|
|
|
TypeNode->ArraySize = 0;
|
|
|
|
TypeNode->Sizeof = Sizeof;
|
2009-01-24 21:09:44 -05:00
|
|
|
TypeNode->Identifier = StrEmpty;
|
2009-01-23 06:34:12 -05:00
|
|
|
TypeNode->Members = NULL;
|
|
|
|
TypeNode->FromType = NULL;
|
|
|
|
TypeNode->DerivedTypeList = NULL;
|
2009-01-23 22:15:02 -05:00
|
|
|
TypeNode->Next = UberType.DerivedTypeList;
|
|
|
|
UberType.DerivedTypeList = TypeNode;
|
2009-01-23 06:34:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* initialise the type system */
|
|
|
|
void TypeInit()
|
|
|
|
{
|
|
|
|
UberType.DerivedTypeList = NULL;
|
|
|
|
TypeAddBaseType(&IntType, TypeInt, sizeof(int));
|
|
|
|
TypeAddBaseType(&CharType, TypeChar, sizeof(char));
|
|
|
|
TypeAddBaseType(&StringType, TypeString, sizeof(Str));
|
|
|
|
TypeAddBaseType(&FPType, TypeFP, sizeof(double));
|
|
|
|
TypeAddBaseType(&VoidType, TypeVoid, 0);
|
|
|
|
TypeAddBaseType(&FunctionType, TypeFunction, sizeof(int));
|
|
|
|
TypeAddBaseType(&MacroType, TypeMacro, sizeof(int));
|
|
|
|
TypeAddBaseType(&Type_Type, TypeType, sizeof(struct ValueType *));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse a struct or union declaration */
|
|
|
|
void TypeParseStruct(struct LexState *Lexer, struct ValueType **Typ, int IsStruct)
|
|
|
|
{
|
|
|
|
union AnyValue LexValue;
|
|
|
|
struct ValueType *MemberType;
|
|
|
|
Str MemberIdentifier;
|
|
|
|
struct Value *MemberValue;
|
|
|
|
|
|
|
|
if (LexGetToken(Lexer, &LexValue) != TokenIdentifier)
|
|
|
|
ProgramFail(Lexer, "struct/union name required");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
if (LexGetPlainToken(Lexer) != TokenLeftBrace)
|
2009-01-23 06:34:12 -05:00
|
|
|
ProgramFail(Lexer, "'{' expected");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
if (StackUsed != 0)
|
2009-01-23 06:34:12 -05:00
|
|
|
ProgramFail(Lexer, "struct/union definitions can only be globals");
|
|
|
|
|
|
|
|
*Typ = TypeGetMatching(Lexer, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, &LexValue.String);
|
2009-01-24 21:09:44 -05:00
|
|
|
(*Typ)->Members = VariableAlloc(Lexer, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry));
|
|
|
|
(*Typ)->Members->HashTable = (void *)(*Typ)->Members + sizeof(struct Table);
|
2009-01-23 06:34:12 -05:00
|
|
|
|
|
|
|
do {
|
|
|
|
TypeParse(Lexer, &MemberType, &MemberIdentifier);
|
|
|
|
|
|
|
|
MemberValue = VariableAllocValueAndData(Lexer, sizeof(int));
|
|
|
|
MemberValue->MustFree = TRUE;
|
2009-01-24 21:09:44 -05:00
|
|
|
MemberValue->Typ = MemberType;
|
2009-01-23 06:34:12 -05:00
|
|
|
if (IsStruct)
|
|
|
|
{ /* allocate this member's location in the struct */
|
2009-01-24 21:09:44 -05:00
|
|
|
MemberValue->Val->Integer = (*Typ)->Sizeof;
|
2009-01-23 06:34:12 -05:00
|
|
|
(*Typ)->Sizeof += MemberValue->Typ->Sizeof;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* union members always start at 0, make sure it's big enough to hold the largest member */
|
2009-01-24 21:09:44 -05:00
|
|
|
MemberValue->Val->Integer = 0;
|
2009-01-23 06:34:12 -05:00
|
|
|
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
|
|
|
|
(*Typ)->Sizeof = MemberValue->Typ->Sizeof;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TableSet((*Typ)->Members, &MemberIdentifier, MemberValue))
|
|
|
|
ProgramFail(Lexer, "member '%S' already defined", &MemberIdentifier);
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
} while (LexPeekPlainToken(Lexer) != TokenRightBrace);
|
2009-01-23 06:34:12 -05:00
|
|
|
|
2009-01-23 22:15:02 -05:00
|
|
|
LexGetPlainToken(Lexer);
|
2009-01-23 06:34:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* parse a type */
|
|
|
|
void TypeParse(struct LexState *Lexer, struct ValueType **Typ, Str *Identifier)
|
|
|
|
{
|
|
|
|
struct LexState Before;
|
2009-01-24 21:09:44 -05:00
|
|
|
enum LexToken Token;
|
2009-01-23 06:34:12 -05:00
|
|
|
union AnyValue LexValue;
|
|
|
|
int Done = FALSE;
|
|
|
|
*Typ = NULL;
|
|
|
|
|
|
|
|
while (!Done)
|
|
|
|
{
|
|
|
|
Before = *Lexer;
|
|
|
|
Token = LexGetToken(Lexer, &LexValue);
|
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenIntType: case TokenLongType: case TokenShortType: *Typ = &IntType; break;
|
|
|
|
case TokenCharType: *Typ = &CharType; break;
|
|
|
|
case TokenFloatType: case TokenDoubleType: *Typ = &FPType; break;
|
|
|
|
case TokenVoidType: *Typ = &VoidType; break;
|
|
|
|
|
|
|
|
case TokenStructType: case TokenUnionType:
|
|
|
|
if (*Typ != NULL)
|
|
|
|
ProgramFail(Lexer, "bad type declaration");
|
|
|
|
|
|
|
|
TypeParseStruct(Lexer, Typ, Token == TokenStructType);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenOpenBracket:
|
|
|
|
if (*Typ != NULL)
|
|
|
|
ProgramFail(Lexer, "bad type declaration");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
TypeParse(Lexer, Typ, Identifier);
|
|
|
|
if (LexGetPlainToken(Lexer) != TokenCloseBracket)
|
2009-01-23 06:34:12 -05:00
|
|
|
ProgramFail(Lexer, "')' expected");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenAsterisk:
|
|
|
|
if (*Typ == NULL)
|
|
|
|
ProgramFail(Lexer, "bad type declaration");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
*Typ = TypeGetMatching(Lexer, *Typ, TypePointer, 0, &StrEmpty);
|
2009-01-23 06:34:12 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenIdentifier:
|
2009-01-24 21:09:44 -05:00
|
|
|
if (*Typ == NULL || Identifier->Len != 0)
|
2009-01-23 06:34:12 -05:00
|
|
|
ProgramFail(Lexer, "bad type declaration");
|
|
|
|
|
|
|
|
*Identifier = LexValue.String;
|
|
|
|
Done = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: *Lexer = Before; Done = TRUE; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*Typ == NULL)
|
|
|
|
ProgramFail(Lexer, "bad type declaration");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
if (Identifier->Len != 0)
|
2009-01-23 06:34:12 -05:00
|
|
|
{ /* parse stuff after the identifier */
|
|
|
|
Done = FALSE;
|
|
|
|
while (!Done)
|
|
|
|
{
|
|
|
|
Before = *Lexer;
|
2009-01-24 21:09:44 -05:00
|
|
|
switch (LexGetPlainToken(Lexer))
|
2009-01-23 06:34:12 -05:00
|
|
|
{
|
2009-01-24 21:09:44 -05:00
|
|
|
case TokenLeftSquareBracket:
|
2009-01-23 22:15:02 -05:00
|
|
|
{
|
2009-01-24 21:09:44 -05:00
|
|
|
struct Value *ArraySizeValue;
|
|
|
|
int ArraySize = 0;
|
2009-01-23 22:15:02 -05:00
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
if (ParseExpression(Lexer, &ArraySizeValue, TRUE))
|
|
|
|
{
|
|
|
|
if (ArraySizeValue->Typ->Base != TypeInt)
|
|
|
|
ProgramFail(Lexer, "array size must be an integer");
|
|
|
|
|
|
|
|
ArraySize = ArraySizeValue->Val->Integer;
|
|
|
|
HeapFree(ArraySizeValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LexGetPlainToken(Lexer) != TokenRightSquareBracket)
|
2009-01-23 22:15:02 -05:00
|
|
|
ProgramFail(Lexer, "']' expected");
|
|
|
|
|
2009-01-24 21:09:44 -05:00
|
|
|
*Typ = TypeGetMatching(Lexer, *Typ, TypeArray, ArraySize, &StrEmpty);
|
2009-01-23 22:15:02 -05:00
|
|
|
}
|
2009-01-23 06:34:12 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenOpenBracket:
|
|
|
|
break; // XXX - finish this
|
|
|
|
|
|
|
|
default: *Lexer = Before; Done = TRUE; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|