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
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)
all: $(TARGET)

2
TODO
View file

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

2
heap.c
View file

@ -132,4 +132,4 @@ void HeapFree(void *Mem)
((struct AllocNode *)Mem)->NextFree = FreeListBig;
FreeListBig = (struct AllocNode *)Mem;
}
}
}

View file

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

10
lex.c
View file

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

150
parse.c
View file

@ -1,34 +1,12 @@
#include <stdio.h>
#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;
/* parameter passing area */
struct Value Parameter[PARAMETER_MAX];
int ParameterUsed = 0;
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 */
int ParseExpression(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 */
void ParseInit()
{
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE);
VariableInit();
IntrinsicInit(&GlobalTable);
IntType.Base = TypeInt;
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;
}
TypeInit();
}
/* 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++)
{
ParseType(FuncLexer, &Typ);
TypeParse(FuncLexer, &Typ);
Token = LexGetToken(FuncLexer, &Identifier);
if (Token != TokenComma && Token != TokenCloseBracket)
{ /* there's an identifier */
@ -226,13 +95,13 @@ void ParseFunctionCall(struct LexState *Lexer, struct Value *Result, Str *FuncNa
if (Result->Typ->Base != TypeFunction)
ProgramFail(Lexer, "not a function - can't call");
StackFrameAdd(Lexer);
VariableStackFrameAdd(Lexer);
if (Result->Val->Integer >= 0)
FuncLexer = FunctionStore[Result->Val->Integer];
else
IntrinsicGetLexer(&FuncLexer, Result->Val->Integer);
ParseType(&FuncLexer, &ReturnType); /* return type */
TypeParse(&FuncLexer, &ReturnType); /* return type */
Result->Typ = TypeVoid;
LexGetPlainToken(&FuncLexer); /* function name again */
ParseParameterList(Lexer, &FuncLexer, TRUE); /* parameters */
@ -461,9 +330,8 @@ void ParseFunctionDefinition(struct LexState *Lexer, Str *Identifier, struct Lex
ProgramFail(Lexer, "function definition expected");
FunctionStore[FunctionStoreUsed].End = Lexer->Pos;
FuncValue = HeapAlloc(sizeof(struct Value) + sizeof(int));
FuncValue = VariableAllocValueAndData(Lexer, sizeof(int));
FuncValue->Typ = &FunctionType;
FuncValue->Val = (union AnyValue *)((void *)FuncValue + sizeof(struct Value));
FuncValue->Val->Integer = FunctionStoreUsed;
FunctionStoreUsed++;
@ -486,9 +354,8 @@ void ParseMacroDefinition(struct LexState *Lexer)
FunctionStore[FunctionStoreUsed] = *Lexer;
LexToEndOfLine(Lexer);
FunctionStore[FunctionStoreUsed].End = Lexer->Pos;
MacroValue = HeapAlloc(sizeof(struct Value) + sizeof(int));
MacroValue = VariableAllocValueAndData(Lexer, sizeof(int));
MacroValue->Typ = &MacroType;
MacroValue->Val = (union AnyValue *)((void *)MacroValue + sizeof(struct Value));
MacroValue->Val->Integer = FunctionStoreUsed;
FunctionStoreUsed++;
@ -628,7 +495,7 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenDoubleType:
case TokenVoidType:
*Lexer = PreState;
ParseType(Lexer, &Typ);
TypeParse(Lexer, &Typ);
if (LexGetToken(Lexer, &LexerValue) != TokenIdentifier)
ProgramFail(Lexer, "identifier expected");
@ -689,4 +556,3 @@ void Parse(const Str *FileName, const Str *Source, int RunIt)
if (Lexer.Pos != Lexer.End)
ProgramFail(&Lexer, "parse error");
}

68
picoc.h
View file

@ -10,6 +10,7 @@
#define STACK_MAX 10 /* maximum function call stack depth */
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */
#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 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))
struct Table;
/* lexical tokens */
enum LexToken
{
@ -84,6 +87,14 @@ enum LexToken
TokenFloatType,
TokenDoubleType,
TokenVoidType,
TokenEnumType,
TokenLongType,
TokenSignedType,
TokenShortType,
TokenStructType,
TokenUnionType,
TokenUnsignedType,
TokenTypedef,
TokenDo,
TokenElse,
TokenFor,
@ -106,6 +117,15 @@ typedef struct _Str
const char *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 */
struct FuncDef
{
@ -126,13 +146,21 @@ enum BaseType
TypeMacro, /* a macro */
TypePointer, /* a pointer */
TypeArray, /* an array of a sub-type */
TypeStruct, /* aggregate type */
TypeUnion, /* merged type */
TypeEnum, /* enumated integer type */
TypeType /* a type (eg. typedef) */
};
struct ValueType
{
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
@ -159,6 +187,8 @@ union AnyValue
Str String;
struct ArrayValue Array;
struct PointerValue Pointer;
struct LexState Lexer;
struct ValueType *Typ;
};
struct Value
@ -181,15 +211,6 @@ struct Table
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 */
struct StackFrame
{
@ -199,12 +220,19 @@ struct StackFrame
};
/* 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 int ParameterUsed;
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 FunctionType;
extern struct ValueType MacroType;
/* str.c */
void StrToC(char *Dest, int DestSize, const Str *Source);
@ -235,7 +263,11 @@ void LexToEndOfLine(struct LexState *Lexer);
/* parse.c */
void ParseInit(void);
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 */
void IntrinsicInit(struct Table *GlobalTable);
@ -250,5 +282,15 @@ int HeapPopStackFrame();
void *HeapAlloc(int Size);
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 "picoc.h"
/* hash function */
static unsigned int TableHash(const Str *Key)
{
unsigned int Hash;
int Count;
int Offset;
const char *KeyPos;
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;
if (Key->Len == 0)
return 0;
else
return ((*Key->Str << 24) | (Key->Str[Key->Len-1] << 16) | (Key->Str[Key->Len >> 1] << 8)) ^ Key->Len;
}
/* initialise a table */
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size)
{
Tbl->Size = Size;
@ -44,6 +33,7 @@ static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos)
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)
{
int HashValue;
@ -71,6 +61,7 @@ static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
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 HashPos;
@ -88,12 +79,14 @@ int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
struct TableEntry *Entry = &Tbl->HashTable[AddAt];
Entry->Key = *Key;
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 HashPos;
@ -107,4 +100,3 @@ int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val)
*Val = Tbl->HashTable[HashPos].Val;
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++;
}