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:
parent
a59be13de3
commit
fad5c6db69
2
Makefile
2
Makefile
|
@ -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
2
TODO
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
10
lex.c
|
@ -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
150
parse.c
|
@ -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
68
picoc.h
|
@ -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
34
table.c
|
@ -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
210
type.c
Normal 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
111
variable.c
Normal 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++;
|
||||||
|
}
|
Loading…
Reference in a new issue