Big changes and progress towards the new type system. Doesn't compile right now. Maybe tomorrow.

git-svn-id: http://picoc.googlecode.com/svn/trunk@35 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-01-23 11:34:12 +00:00
parent a59be13de3
commit fad5c6db69
10 changed files with 411 additions and 181 deletions

View file

@ -3,7 +3,7 @@ CFLAGS=-Wall -g
LIBS=-lm LIBS=-lm
TARGET = picoc TARGET = picoc
SRCS = picoc.c table.c str.c parse.c lex.c intrinsic.c heap.c SRCS = picoc.c table.c str.c parse.c lex.c intrinsic.c heap.c type.c variable.c
OBJS := $(SRCS:%.c=%.o) OBJS := $(SRCS:%.c=%.o)
all: $(TARGET) all: $(TARGET)

2
TODO
View file

@ -17,3 +17,5 @@ New type system:
Also: Also:
* Change function store system to use dynamic allocation * Change function store system to use dynamic allocation
* Check for Alloc returns checking NULL

View file

@ -47,7 +47,7 @@ void IntrinsicInit(struct Table *GlobalTable)
Source.Str = Intrinsics[Count].Prototype; Source.Str = Intrinsics[Count].Prototype;
Source.Len = strlen(Source.Str); Source.Len = strlen(Source.Str);
LexInit(&Lexer, &Source, &IntrinsicFilename, Count+1); LexInit(&Lexer, &Source, &IntrinsicFilename, Count+1);
ParseType(&Lexer, &Typ); TypeParse(&Lexer, &Typ);
LexGetToken(&Lexer, &Identifier); LexGetToken(&Lexer, &Identifier);
IntrinsicReferenceNo[Count] = -1 - Count; IntrinsicReferenceNo[Count] = -1 - Count;
IntrinsicValue[Count].Typ = &FunctionType; IntrinsicValue[Count].Typ = &FunctionType;
@ -70,4 +70,3 @@ void IntrinsicCall(struct LexState *Lexer, struct Value *Result, struct ValueTyp
Intrinsics[-1-IntrinsicId].Func(); Intrinsics[-1-IntrinsicId].Func();
Result->Typ = &VoidType; Result->Typ = &VoidType;
} }

10
lex.c
View file

@ -29,12 +29,20 @@ static struct ReservedWord ReservedWords[] =
{ "do", TokenDo }, { "do", TokenDo },
{ "double", TokenDoubleType }, { "double", TokenDoubleType },
{ "else", TokenElse }, { "else", TokenElse },
{ "enum", TokenEnumType },
{ "float", TokenFloatType }, { "float", TokenFloatType },
{ "for", TokenFor }, { "for", TokenFor },
{ "if", TokenIf }, { "if", TokenIf },
{ "int", TokenIntType }, { "int", TokenIntType },
{ "long", TokenLongType },
{ "return", TokenReturn }, { "return", TokenReturn },
{ "signed", TokenSignedType },
{ "short", TokenShortType },
{ "struct", TokenStructType },
{ "switch", TokenSwitch }, { "switch", TokenSwitch },
{ "typedef", TokenTypedef },
{ "union", TokenUnionType },
{ "unsigned", TokenUnsignedType },
{ "void", TokenVoidType }, { "void", TokenVoidType },
{ "while", TokenWhile } { "while", TokenWhile }
}; };
@ -229,6 +237,7 @@ enum LexToken LexGetToken(struct LexState *Lexer, union AnyValue *Value)
} }
else else
{ {
CachedPos = Lexer->Pos;
CachedToken = LexGetTokenUncached(Lexer, Value); CachedToken = LexGetTokenUncached(Lexer, Value);
CachedLexer = *Lexer; CachedLexer = *Lexer;
CachedValue = *Value; CachedValue = *Value;
@ -263,4 +272,3 @@ void LexToEndOfLine(struct LexState *Lexer)
while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n') while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n')
Lexer->Pos++; Lexer->Pos++;
} }

150
parse.c
View file

@ -1,34 +1,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "picoc.h" #include "picoc.h"
/* the table of global definitions */
struct Table GlobalTable;
struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE];
/* the table of function definitions */
struct LexState FunctionStore[FUNCTION_STORE_MAX];
int FunctionStoreUsed = 0;
/* the stack */
struct StackFrame Stack[STACK_MAX];
int StackUsed = 0;
/* parameter passing area */ /* parameter passing area */
struct Value Parameter[PARAMETER_MAX]; struct Value Parameter[PARAMETER_MAX];
int ParameterUsed = 0; int ParameterUsed = 0;
struct Value ReturnValue; struct Value ReturnValue;
/* some basic types */
struct ValueType IntType;
struct ValueType CharType;
struct ValueType StringType;
struct ValueType FPType;
struct ValueType VoidType;
struct ValueType FunctionType;
struct ValueType MacroType;
/* local prototypes */ /* local prototypes */
int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt); int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt);
void ParseIntExpression(struct LexState *Lexer, struct Value *Result, int RunIt); void ParseIntExpression(struct LexState *Lexer, struct Value *Result, int RunIt);
@ -39,118 +17,9 @@ int ParseArguments(struct LexState *Lexer, int RunIt);
/* initialise the parser */ /* initialise the parser */
void ParseInit() void ParseInit()
{ {
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE); VariableInit();
IntrinsicInit(&GlobalTable); IntrinsicInit(&GlobalTable);
IntType.Base = TypeInt; TypeInit();
IntType.SubType = NULL;
CharType.Base = TypeChar;
CharType.SubType = NULL;
StringType.Base = TypeString;
StringType.SubType = NULL;
FPType.Base = TypeFP;
FPType.SubType = NULL;
VoidType.Base = TypeVoid;
VoidType.SubType = NULL;
FunctionType.Base = TypeFunction;
FunctionType.SubType = NULL;
MacroType.Base = TypeMacro;
MacroType.SubType = NULL;
}
/* find out the size of a type */
int ParseSizeofType(struct ValueType *Typ)
{
switch (Typ->Base)
{
case TypeVoid: return 0;
case TypeInt: return sizeof(int);
case TypeFP: return sizeof(double);
case TypeChar: return sizeof(char);
case TypeString: return sizeof(Str);
case TypeFunction: return sizeof(int);
case TypeMacro: return sizeof(int);
case TypePointer: return sizeof(struct PointerValue);
case TypeArray: return 0; // XXX - fixme
case TypeType: return sizeof(struct ValueType *);
}
return 0;
}
/* allocate a value either on the heap or the stack using space dependent on what type we want */
struct Value *ParseAllocValueFromType(struct ValueType *Typ)
{
struct Value *NewValue;
if (StackUsed == 0)
{ /* it's a global */
NewValue = HeapAlloc(sizeof(struct Value) + ParseSizeofType(Typ));
NewValue->MustFree = TRUE;
}
else
{ /* allocated on the stack */
NewValue = HeapAllocStack(sizeof(struct Value) + ParseSizeofType(Typ));
NewValue->MustFree = FALSE;
}
NewValue->Typ = Typ;
NewValue->Val = (union AnyValue *)((void *)NewValue + sizeof(struct Value));
return NewValue;
}
/* allocate a value either on the heap or the stack and copy its value */
struct Value *ParseAllocValueAndCopy(struct Value *FromValue)
{
struct Value *NewValue = ParseAllocValueFromType(FromValue->Typ);
memcpy(NewValue->Val, FromValue->Val, ParseSizeofType(FromValue->Typ));
return NewValue;
}
/* define a variable */
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue)
{
if (!TableSet((StackUsed == 0) ? &GlobalTable : &Stack[StackUsed-1].LocalTable, Ident, ParseAllocValueAndCopy(InitValue)))
ProgramFail(Lexer, "'%S' is already defined", Ident);
}
/* get the value of a variable. must be defined */
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value *Val, struct Value **LVal)
{
if (StackUsed == 0 || !TableGet(&Stack[StackUsed-1].LocalTable, Ident, LVal))
{
if (!TableGet(&GlobalTable, Ident, LVal))
ProgramFail(Lexer, "'%S' is undefined", Ident);
}
*Val = **LVal;
}
/* add a stack frame when doing a function call */
void StackFrameAdd(struct LexState *Lexer)
{
struct StackFrame *NewFrame = &Stack[StackUsed];
if (StackUsed >= STACK_MAX)
ProgramFail(Lexer, "too many nested function calls");
NewFrame->ReturnLex = *Lexer;
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE);
StackUsed++;
}
/* parse a type specification */
int ParseType(struct LexState *Lexer, struct ValueType **Typ)
{
struct LexState Before = *Lexer;
enum LexToken Token = LexGetPlainToken(Lexer);
switch (Token)
{
case TokenIntType: case TokenCharType: *Typ = &IntType; return TRUE;
case TokenFloatType: case TokenDoubleType: *Typ = &FPType; return TRUE;
case TokenVoidType: *Typ = &VoidType; return TRUE;
default: *Lexer = Before; return FALSE;
}
} }
/* parse a parameter list, defining parameters as local variables in the current scope */ /* parse a parameter list, defining parameters as local variables in the current scope */
@ -163,7 +32,7 @@ void ParseParameterList(struct LexState *CallLexer, struct LexState *FuncLexer,
for (ParamCount = 0; ParamCount < ParameterUsed; ParamCount++) for (ParamCount = 0; ParamCount < ParameterUsed; ParamCount++)
{ {
ParseType(FuncLexer, &Typ); TypeParse(FuncLexer, &Typ);
Token = LexGetToken(FuncLexer, &Identifier); Token = LexGetToken(FuncLexer, &Identifier);
if (Token != TokenComma && Token != TokenCloseBracket) if (Token != TokenComma && Token != TokenCloseBracket)
{ /* there's an identifier */ { /* there's an identifier */
@ -226,13 +95,13 @@ void ParseFunctionCall(struct LexState *Lexer, struct Value *Result, Str *FuncNa
if (Result->Typ->Base != TypeFunction) if (Result->Typ->Base != TypeFunction)
ProgramFail(Lexer, "not a function - can't call"); ProgramFail(Lexer, "not a function - can't call");
StackFrameAdd(Lexer); VariableStackFrameAdd(Lexer);
if (Result->Val->Integer >= 0) if (Result->Val->Integer >= 0)
FuncLexer = FunctionStore[Result->Val->Integer]; FuncLexer = FunctionStore[Result->Val->Integer];
else else
IntrinsicGetLexer(&FuncLexer, Result->Val->Integer); IntrinsicGetLexer(&FuncLexer, Result->Val->Integer);
ParseType(&FuncLexer, &ReturnType); /* return type */ TypeParse(&FuncLexer, &ReturnType); /* return type */
Result->Typ = TypeVoid; Result->Typ = TypeVoid;
LexGetPlainToken(&FuncLexer); /* function name again */ LexGetPlainToken(&FuncLexer); /* function name again */
ParseParameterList(Lexer, &FuncLexer, TRUE); /* parameters */ ParseParameterList(Lexer, &FuncLexer, TRUE); /* parameters */
@ -461,9 +330,8 @@ void ParseFunctionDefinition(struct LexState *Lexer, Str *Identifier, struct Lex
ProgramFail(Lexer, "function definition expected"); ProgramFail(Lexer, "function definition expected");
FunctionStore[FunctionStoreUsed].End = Lexer->Pos; FunctionStore[FunctionStoreUsed].End = Lexer->Pos;
FuncValue = HeapAlloc(sizeof(struct Value) + sizeof(int)); FuncValue = VariableAllocValueAndData(Lexer, sizeof(int));
FuncValue->Typ = &FunctionType; FuncValue->Typ = &FunctionType;
FuncValue->Val = (union AnyValue *)((void *)FuncValue + sizeof(struct Value));
FuncValue->Val->Integer = FunctionStoreUsed; FuncValue->Val->Integer = FunctionStoreUsed;
FunctionStoreUsed++; FunctionStoreUsed++;
@ -486,9 +354,8 @@ void ParseMacroDefinition(struct LexState *Lexer)
FunctionStore[FunctionStoreUsed] = *Lexer; FunctionStore[FunctionStoreUsed] = *Lexer;
LexToEndOfLine(Lexer); LexToEndOfLine(Lexer);
FunctionStore[FunctionStoreUsed].End = Lexer->Pos; FunctionStore[FunctionStoreUsed].End = Lexer->Pos;
MacroValue = HeapAlloc(sizeof(struct Value) + sizeof(int)); MacroValue = VariableAllocValueAndData(Lexer, sizeof(int));
MacroValue->Typ = &MacroType; MacroValue->Typ = &MacroType;
MacroValue->Val = (union AnyValue *)((void *)MacroValue + sizeof(struct Value));
MacroValue->Val->Integer = FunctionStoreUsed; MacroValue->Val->Integer = FunctionStoreUsed;
FunctionStoreUsed++; FunctionStoreUsed++;
@ -628,7 +495,7 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenDoubleType: case TokenDoubleType:
case TokenVoidType: case TokenVoidType:
*Lexer = PreState; *Lexer = PreState;
ParseType(Lexer, &Typ); TypeParse(Lexer, &Typ);
if (LexGetToken(Lexer, &LexerValue) != TokenIdentifier) if (LexGetToken(Lexer, &LexerValue) != TokenIdentifier)
ProgramFail(Lexer, "identifier expected"); ProgramFail(Lexer, "identifier expected");
@ -689,4 +556,3 @@ void Parse(const Str *FileName, const Str *Source, int RunIt)
if (Lexer.Pos != Lexer.End) if (Lexer.Pos != Lexer.End)
ProgramFail(&Lexer, "parse error"); ProgramFail(&Lexer, "parse error");
} }

68
picoc.h
View file

@ -10,6 +10,7 @@
#define STACK_MAX 10 /* maximum function call stack depth */ #define STACK_MAX 10 /* maximum function call stack depth */
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */ #define PARAMETER_MAX 10 /* maximum number of parameters to a function */
#define LOCAL_TABLE_SIZE 11 /* maximum number of local variables */ #define LOCAL_TABLE_SIZE 11 /* maximum number of local variables */
#define STRUCT_TABLE_SIZE 11 /* maximum number of struct/union members */
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */ #define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
#define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */ #define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */
@ -37,6 +38,8 @@
#define ISVALUETYPE(t) (((t)->Base == TypeInt) || ((t)->Base == TypeFP) || ((t)->Base == TypeString)) #define ISVALUETYPE(t) (((t)->Base == TypeInt) || ((t)->Base == TypeFP) || ((t)->Base == TypeString))
struct Table;
/* lexical tokens */ /* lexical tokens */
enum LexToken enum LexToken
{ {
@ -84,6 +87,14 @@ enum LexToken
TokenFloatType, TokenFloatType,
TokenDoubleType, TokenDoubleType,
TokenVoidType, TokenVoidType,
TokenEnumType,
TokenLongType,
TokenSignedType,
TokenShortType,
TokenStructType,
TokenUnionType,
TokenUnsignedType,
TokenTypedef,
TokenDo, TokenDo,
TokenElse, TokenElse,
TokenFor, TokenFor,
@ -106,6 +117,15 @@ typedef struct _Str
const char *Str; const char *Str;
} Str; } Str;
/* lexer state - so we can lex nested files */
struct LexState
{
int Line;
const char *Pos;
const char *End;
const Str *FileName;
};
/* function definition - really just where it is in the source file */ /* function definition - really just where it is in the source file */
struct FuncDef struct FuncDef
{ {
@ -126,13 +146,21 @@ enum BaseType
TypeMacro, /* a macro */ TypeMacro, /* a macro */
TypePointer, /* a pointer */ TypePointer, /* a pointer */
TypeArray, /* an array of a sub-type */ TypeArray, /* an array of a sub-type */
TypeStruct, /* aggregate type */
TypeUnion, /* merged type */
TypeEnum, /* enumated integer type */
TypeType /* a type (eg. typedef) */ TypeType /* a type (eg. typedef) */
}; };
struct ValueType struct ValueType
{ {
enum BaseType Base; /* what kind of type this is */ enum BaseType Base; /* what kind of type this is */
struct ValueType *SubType; /* sub-type for pointer and array types */ int ArraySize; /* the size of an array type */
int Sizeof; /* the storage required */
struct ValueType *FromType; /* the type we're derived from (or NULL) */
struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */
struct ValueType *Next; /* next item in the derived type list */
struct Table *Members; /* members of a struct, union or enum */
}; };
struct ArrayValue struct ArrayValue
@ -159,6 +187,8 @@ union AnyValue
Str String; Str String;
struct ArrayValue Array; struct ArrayValue Array;
struct PointerValue Pointer; struct PointerValue Pointer;
struct LexState Lexer;
struct ValueType *Typ;
}; };
struct Value struct Value
@ -181,15 +211,6 @@ struct Table
struct TableEntry *HashTable; struct TableEntry *HashTable;
}; };
/* lexer state - so we can lex nested files */
struct LexState
{
int Line;
const char *Pos;
const char *End;
const Str *FileName;
};
/* stack frame for function calls */ /* stack frame for function calls */
struct StackFrame struct StackFrame
{ {
@ -199,12 +220,19 @@ struct StackFrame
}; };
/* globals */ /* globals */
struct Table GlobalTable; extern struct Table GlobalTable;
extern struct LexState FunctionStore[FUNCTION_STORE_MAX];
extern int FunctionStoreUsed;
extern struct Value Parameter[PARAMETER_MAX]; extern struct Value Parameter[PARAMETER_MAX];
extern int ParameterUsed; extern int ParameterUsed;
extern struct Value ReturnValue; extern struct Value ReturnValue;
extern struct ValueType IntType;
extern struct ValueType CharType;
extern struct ValueType StringType;
extern struct ValueType FPType;
extern struct ValueType VoidType; extern struct ValueType VoidType;
extern struct ValueType FunctionType; extern struct ValueType FunctionType;
extern struct ValueType MacroType;
/* str.c */ /* str.c */
void StrToC(char *Dest, int DestSize, const Str *Source); void StrToC(char *Dest, int DestSize, const Str *Source);
@ -235,7 +263,11 @@ void LexToEndOfLine(struct LexState *Lexer);
/* parse.c */ /* parse.c */
void ParseInit(void); void ParseInit(void);
void Parse(const Str *FileName, const Str *Source, int RunIt); void Parse(const Str *FileName, const Str *Source, int RunIt);
int ParseType(struct LexState *Lexer, struct ValueType **Typ);
/* type.c */
void TypeInit();
int TypeSizeof(struct ValueType *Typ);
int TypeParse(struct LexState *Lexer, struct ValueType **Typ, Str *Identifier);
/* intrinsic.c */ /* intrinsic.c */
void IntrinsicInit(struct Table *GlobalTable); void IntrinsicInit(struct Table *GlobalTable);
@ -250,5 +282,15 @@ int HeapPopStackFrame();
void *HeapAlloc(int Size); void *HeapAlloc(int Size);
void HeapFree(void *Mem); void HeapFree(void *Mem);
#endif /* PICOC_H */ /* variable.c */
void VariableInit();
void *VariableAlloc(struct LexState *Lexer, int Size);
struct Value *VariableAllocValueAndData(struct LexState *Lexer, int DataSize);
struct Value *VariableAllocValueAndCopy(struct LexState *Lexer, struct Value *FromValue);
struct Value *VariableAllocValueFromType(struct LexState *Lexer, struct ValueType *Typ);
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue);
int VariableDefined(Str *Ident);
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value *Val, struct Value **LVal);
void VariableStackFrameAdd(struct LexState *Lexer);
#endif /* PICOC_H */

34
table.c
View file

@ -1,27 +1,16 @@
#include <string.h> #include <string.h>
#include "picoc.h" #include "picoc.h"
/* hash function */
static unsigned int TableHash(const Str *Key) static unsigned int TableHash(const Str *Key)
{ {
unsigned int Hash; if (Key->Len == 0)
int Count; return 0;
int Offset; else
const char *KeyPos; return ((*Key->Str << 24) | (Key->Str[Key->Len-1] << 16) | (Key->Str[Key->Len >> 1] << 8)) ^ Key->Len;
Hash = Key->Len;
KeyPos = Key->Str;
Offset = 8;
for (Count = 0; Count < Key->Len; Count++, Offset+=7)
{
if (Offset > sizeof(unsigned int) * 8 - 7)
Offset -= (sizeof(unsigned int)-1) * 8;
Hash ^= *KeyPos++ << Offset;
}
return Hash;
} }
/* initialise a table */
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size) void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size)
{ {
Tbl->Size = Size; Tbl->Size = Size;
@ -44,6 +33,7 @@ static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos)
return -2; /* wrong key */ return -2; /* wrong key */
} }
/* search a table for an identifier. sets AddAt to where to add it at if not found */
static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt) static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
{ {
int HashValue; int HashValue;
@ -71,6 +61,7 @@ static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
return -1; return -1;
} }
/* set an identifier to a value. returns FALSE if it already exists */
int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val) int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
{ {
int HashPos; int HashPos;
@ -88,12 +79,14 @@ int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
struct TableEntry *Entry = &Tbl->HashTable[AddAt]; struct TableEntry *Entry = &Tbl->HashTable[AddAt];
Entry->Key = *Key; Entry->Key = *Key;
Entry->Val = Val; Entry->Val = Val;
}
}
return TRUE; return TRUE;
} }
}
else
return FALSE;
}
/* find a value in a table. returns FALSE if not found */
int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val) int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val)
{ {
int HashPos; int HashPos;
@ -107,4 +100,3 @@ int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val)
*Val = Tbl->HashTable[HashPos].Val; *Val = Tbl->HashTable[HashPos].Val;
return TRUE; return TRUE;
} }

210
type.c Normal file
View file

@ -0,0 +1,210 @@
#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)
{
struct ValueType *NewType = VariableAlloc(sizeof(struct ValueType));
NewType->Base = Base;
NewType->ArraySize = ArraySize;
NewType->Sizeof = Sizeof;
NewType->Identifier = Identifier;
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;
while (ThisType != NULL && (ThisType->Base != Base || ThisType->ArraySize != ArraySize || !StrEqual(ThisType->Identifier, Identifier))
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;
TypeNode->Identifier = Identifier;
TypeNode->Members = NULL;
TypeNode->FromType = NULL;
TypeNode->DerivedTypeList = NULL;
TypeNode->Next = UberType->DerivedTypeList;
UberType->DerivedTypeList = NewType;
}
/* 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;
int TotalSize = 0;
struct ValueType *MemberType;
Str MemberIdentifier;
struct Value *MemberValue;
if (LexGetToken(Lexer, &LexValue) != TokenIdentifier)
ProgramFail(Lexer, "struct/union name required");
if (LexGetTokenOnly(Lexer) != TokenOpenBrace)
ProgramFail(Lexer, "'{' expected");
if (StackLevel != 0)
ProgramFail(Lexer, "struct/union definitions can only be globals");
*Typ = TypeGetMatching(Lexer, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, &LexValue.String);
(*Typ)->Members = VariableAlloc(sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry));
(*Typ)->Members->HashTable = (struct Table *)((void *)(*Typ)->Members + sizeof(struct Table));
do {
TypeParse(Lexer, &MemberType, &MemberIdentifier);
MemberValue = VariableAllocValueAndData(Lexer, sizeof(int));
MemberValue->MustFree = TRUE;
MemberValue->Typ = &MemberType;
if (IsStruct)
{ /* allocate this member's location in the struct */
MemberValue->Value->Integer = (*Typ)->Sizeof;
(*Typ)->Sizeof += MemberValue->Typ->Sizeof;
}
else
{ /* union members always start at 0, make sure it's big enough to hold the largest member */
MemberValue->Value->Integer = 0;
if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof)
(*Typ)->Sizeof = MemberValue->Typ->Sizeof;
}
if (!TableSet((*Typ)->Members, &MemberIdentifier, MemberValue))
ProgramFail(Lexer, "member '%S' already defined", &MemberIdentifier);
} while (LexPeekTokenOnly(Lexer) != TokenCloseBrace);
LexGetTokenOnly(Lexer);
}
/* parse a type */
void TypeParse(struct LexState *Lexer, struct ValueType **Typ, Str *Identifier)
{
struct LexState Before;
struct LexToken Token;
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");
TypeParseDeclarator(Lexer, Typ, Identifier);
if (LexGetTokenOnly(Lexer) != TokenCloseBracket)
ProgramFail(Lexer, "')' expected");
break;
case TokenAsterisk:
if (*Typ == NULL)
ProgramFail(Lexer, "bad type declaration");
*Typ = TypeGetMatching(Lexer, *Typ, TypePointer, 0);
break;
case TokenIdentifier:
if (*Typ == NULL || Identifier->Length != 0)
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");
if (Identifier->Length != 0)
{ /* parse stuff after the identifier */
Done = FALSE;
while (!Done)
{
Before = *Lexer;
switch (LexGetTokenOnly(Lexer))
{
case TokenOpenSquareBracket:
if (ParseExpression(xxx)
XXX - get a closing square bracket
*Typ = TypeGetMatching(Lexer, *Typ, TypeArray, xxx);
break;
case TokenOpenBracket:
break; // XXX - finish this
default: *Lexer = Before; Done = TRUE; break;
}
}
}
}

111
variable.c Normal file
View file

@ -0,0 +1,111 @@
#include <string.h>
#include "picoc.h"
/* the table of global definitions */
struct Table GlobalTable;
struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE];
/* the table of function definitions */
struct LexState FunctionStore[FUNCTION_STORE_MAX];
int FunctionStoreUsed = 0;
/* the stack */
struct StackFrame Stack[STACK_MAX];
int StackUsed = 0;
/* initialise the variable system */
void VariableInit()
{
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE);
}
/* allocate some memory, either on the heap or the stack and check if we've run out */
void *VariableAlloc(struct LexState *Lexer, int Size)
{
void *NewValue;
if (StackUsed == 0)
NewValue = HeapAlloc(Size);
else
NewValue = HeapAllocStack(Size);
if (NewValue == NULL)
ProgramFail(Lexer, "out of memory");
return NewValue;
}
/* allocate a value either on the heap or the stack using space dependent on what type we want */
struct Value *VariableAllocValueAndData(struct LexState *Lexer, int DataSize)
{
struct Value *NewValue = VariableAlloc(Lexer, DataSize);
NewValue->Val = (union AnyValue *)((void *)NewValue + sizeof(struct Value));
NewValue->MustFree = (StackUsed == 0);
return NewValue;
}
/* allocate a value given its type */
struct Value *VariableAllocValueFromType(struct LexState *Lexer, struct ValueType *Typ)
{
struct Value *NewValue = VariableAllocValueAndData(Typ->Sizeof);
NewValue->Typ = Typ;
return NewValue;
}
/* allocate a value either on the heap or the stack and copy its value */
struct Value *VariableAllocValueAndCopy(struct LexState *Lexer, struct Value *FromValue)
{
struct Value *NewValue = VariableAllocValueAndData(TypeSizeof(FromValue->Typ));
NewValue->Typ = FromValue->Typ;
memcpy(NewValue->Val, FromValue->Val, TypeSizeof(FromValue->Typ));
return NewValue;
}
/* define a variable */
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue)
{
if (!TableSet((StackUsed == 0) ? &GlobalTable : &Stack[StackUsed-1].LocalTable, Ident, VariableAllocValueAndCopy(InitValue)))
ProgramFail(Lexer, "'%S' is already defined", Ident);
}
/* check if a variable with a given name is defined */
int VariableDefined(Str *Ident)
{
struct Value *FoundValue;
if (StackUsed == 0 || !TableGet(&Stack[StackUsed-1].LocalTable, Ident, &FoundValue))
{
if (!TableGet(&GlobalTable, Ident, &FoundValue))
return FALSE;
}
return TRUE;
}
/* get the value of a variable. must be defined */
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value *Val, struct Value **LVal)
{
if (StackUsed == 0 || !TableGet(&Stack[StackUsed-1].LocalTable, Ident, LVal))
{
if (!TableGet(&GlobalTable, Ident, LVal))
ProgramFail(Lexer, "'%S' is undefined", Ident);
}
*Val = **LVal;
}
/* add a stack frame when doing a function call */
void VariableStackFrameAdd(struct LexState *Lexer)
{
struct StackFrame *NewFrame = &Stack[StackUsed];
if (StackUsed >= STACK_MAX)
ProgramFail(Lexer, "too many nested function calls");
NewFrame->ReturnLex = *Lexer;
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE);
StackUsed++;
}