Merged in a pile of changes from broscutamaker

git-svn-id: http://picoc.googlecode.com/svn/trunk@599 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2013-03-16 07:39:34 +00:00
parent 3d5e022272
commit b5a600a749
14 changed files with 484 additions and 90 deletions

View file

@ -63,6 +63,7 @@ void PrintType(struct ValueType *Typ, IOFILE *Stream)
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break; case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break; case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break; case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
case TypeUnsignedChar: PrintStr("unsigned char", Stream); break;
#ifndef NO_FP #ifndef NO_FP
case TypeFP: PrintStr("double", Stream); break; case TypeFP: PrintStr("double", Stream); break;
#endif #endif

View file

@ -7,7 +7,7 @@
#define MAX_FORMAT 80 #define MAX_FORMAT 80
#define MAX_SCANF_ARGS 10 #define MAX_SCANF_ARGS 10
static int ZeroValue = 0; static int Stdio_ZeroValue = 0;
static int EOFValue = EOF; static int EOFValue = EOF;
static int SEEK_SETValue = SEEK_SET; static int SEEK_SETValue = SEEK_SET;
static int SEEK_CURValue = SEEK_CUR; static int SEEK_CURValue = SEEK_CUR;
@ -103,7 +103,7 @@ void StdioOutPuts(const char *Str, StdOutStream *Stream)
} }
/* printf-style format of an int or other word-sized object */ /* printf-style format of an int or other word-sized object */
void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned int Value) void StdioFprintfWord(StdOutStream *Stream, const char *Format, unsigned long Value)
{ {
if (Stream->FilePtr != NULL) if (Stream->FilePtr != NULL)
Stream->CharCount += fprintf(Stream->FilePtr, Format, Value); Stream->CharCount += fprintf(Stream->FilePtr, Format, Value);
@ -712,7 +712,7 @@ void StdioSetupFunc(Picoc *pc)
/* define NULL, TRUE and FALSE */ /* define NULL, TRUE and FALSE */
if (!VariableDefined(pc, TableStrRegister(pc, "NULL"))) if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE); VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdio_ZeroValue, FALSE);
} }
/* portability-related I/O calls */ /* portability-related I/O calls */

View file

@ -3,7 +3,7 @@
#ifndef BUILTIN_MINI_STDLIB #ifndef BUILTIN_MINI_STDLIB
static int ZeroValue = 0; static int Stdlib_ZeroValue = 0;
#ifndef NO_FP #ifndef NO_FP
void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
@ -168,7 +168,7 @@ void StdlibSetupFunc(Picoc *pc)
{ {
/* define NULL, TRUE and FALSE */ /* define NULL, TRUE and FALSE */
if (!VariableDefined(pc, TableStrRegister(pc, "NULL"))) if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE); VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdlib_ZeroValue, FALSE);
} }
#endif /* !BUILTIN_MINI_STDLIB */ #endif /* !BUILTIN_MINI_STDLIB */

View file

@ -3,7 +3,7 @@
#ifndef BUILTIN_MINI_STDLIB #ifndef BUILTIN_MINI_STDLIB
static int ZeroValue = 0; static int String_ZeroValue = 0;
void StringStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) void StringStrcpy(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{ {
@ -180,7 +180,7 @@ void StringSetupFunc(Picoc *pc)
{ {
/* define NULL */ /* define NULL */
if (!VariableDefined(pc, TableStrRegister(pc, "NULL"))) if (!VariableDefined(pc, TableStrRegister(pc, "NULL")))
VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&ZeroValue, FALSE); VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&String_ZeroValue, FALSE);
} }
#endif /* !BUILTIN_MINI_STDLIB */ #endif /* !BUILTIN_MINI_STDLIB */

View file

@ -6,7 +6,6 @@
/* whether evaluation is left to right for a given precedence level */ /* whether evaluation is left to right for a given precedence level */
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14) #define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
#define BRACKET_PRECEDENCE 20 #define BRACKET_PRECEDENCE 20
#define IS_TYPE_TOKEN(t) ((t) >= TokenIntType && (t) <= TokenUnsignedType)
/* If the destination is not float, we can't assign a floating value to it, we need to convert it to integer instead */ /* If the destination is not float, we can't assign a floating value to it, we need to convert it to integer instead */
#define ASSIGN_FP_OR_INT(value) \ #define ASSIGN_FP_OR_INT(value) \
@ -142,6 +141,26 @@ void ExpressionStackShow(struct ExpressionStack *StackTop)
} }
#endif #endif
int IsTypeToken(struct ParseState * Parser, enum LexToken t, struct Value * LexValue)
{
if (t >= TokenIntType && t <= TokenUnsignedType)
return 1; /* base type */
/* typedef'ed type? */
if (t == TokenIdentifier) /* see TypeParseFront, case TokenIdentifier and ParseTypedef */
{
struct Value * VarValue;
if (VariableDefined(Parser->pc, LexValue->Val->Pointer))
{
VariableGet(Parser->pc, Parser, LexValue->Val->Pointer, &VarValue);
if (VarValue->Typ == &Parser->pc->TypeType)
return 1;
}
}
return 0;
}
long ExpressionCoerceInteger(struct Value *Val) long ExpressionCoerceInteger(struct Value *Val)
{ {
switch (Val->Typ->Base) switch (Val->Typ->Base)
@ -153,6 +172,7 @@ long ExpressionCoerceInteger(struct Value *Val)
case TypeUnsignedInt: return (long)Val->Val->UnsignedInteger; case TypeUnsignedInt: return (long)Val->Val->UnsignedInteger;
case TypeUnsignedShort: return (long)Val->Val->UnsignedShortInteger; case TypeUnsignedShort: return (long)Val->Val->UnsignedShortInteger;
case TypeUnsignedLong: return (long)Val->Val->UnsignedLongInteger; case TypeUnsignedLong: return (long)Val->Val->UnsignedLongInteger;
case TypeUnsignedChar: return (long)Val->Val->UnsignedCharacter;
case TypePointer: return (long)Val->Val->Pointer; case TypePointer: return (long)Val->Val->Pointer;
#ifndef NO_FP #ifndef NO_FP
case TypeFP: return (long)Val->Val->FP; case TypeFP: return (long)Val->Val->FP;
@ -172,6 +192,7 @@ unsigned long ExpressionCoerceUnsignedInteger(struct Value *Val)
case TypeUnsignedInt: return (unsigned long)Val->Val->UnsignedInteger; case TypeUnsignedInt: return (unsigned long)Val->Val->UnsignedInteger;
case TypeUnsignedShort: return (unsigned long)Val->Val->UnsignedShortInteger; case TypeUnsignedShort: return (unsigned long)Val->Val->UnsignedShortInteger;
case TypeUnsignedLong: return (unsigned long)Val->Val->UnsignedLongInteger; case TypeUnsignedLong: return (unsigned long)Val->Val->UnsignedLongInteger;
case TypeUnsignedChar: return (unsigned long)Val->Val->UnsignedCharacter;
case TypePointer: return (unsigned long)Val->Val->Pointer; case TypePointer: return (unsigned long)Val->Val->Pointer;
#ifndef NO_FP #ifndef NO_FP
case TypeFP: return (unsigned long)Val->Val->FP; case TypeFP: return (unsigned long)Val->Val->FP;
@ -196,6 +217,7 @@ double ExpressionCoerceFP(struct Value *Val)
case TypeUnsignedInt: UnsignedVal = Val->Val->UnsignedInteger; return (double)UnsignedVal; case TypeUnsignedInt: UnsignedVal = Val->Val->UnsignedInteger; return (double)UnsignedVal;
case TypeUnsignedShort: UnsignedVal = Val->Val->UnsignedShortInteger; return (double)UnsignedVal; case TypeUnsignedShort: UnsignedVal = Val->Val->UnsignedShortInteger; return (double)UnsignedVal;
case TypeUnsignedLong: UnsignedVal = Val->Val->UnsignedLongInteger; return (double)UnsignedVal; case TypeUnsignedLong: UnsignedVal = Val->Val->UnsignedLongInteger; return (double)UnsignedVal;
case TypeUnsignedChar: UnsignedVal = Val->Val->UnsignedCharacter; return (double)UnsignedVal;
case TypeFP: return Val->Val->FP; case TypeFP: return Val->Val->FP;
default: return 0.0; default: return 0.0;
} }
@ -209,6 +231,7 @@ double ExpressionCoerceFP(struct Value *Val)
case TypeUnsignedInt: return (double)Val->Val->UnsignedInteger; case TypeUnsignedInt: return (double)Val->Val->UnsignedInteger;
case TypeUnsignedShort: return (double)Val->Val->UnsignedShortInteger; case TypeUnsignedShort: return (double)Val->Val->UnsignedShortInteger;
case TypeUnsignedLong: return (double)Val->Val->UnsignedLongInteger; case TypeUnsignedLong: return (double)Val->Val->UnsignedLongInteger;
case TypeUnsignedChar: return (double)Val->Val->UnsignedCharacter;
case TypeFP: return (double)Val->Val->FP; case TypeFP: return (double)Val->Val->FP;
default: return 0.0; default: return 0.0;
} }
@ -233,11 +256,12 @@ long ExpressionAssignInt(struct ParseState *Parser, struct Value *DestValue, lon
{ {
case TypeInt: DestValue->Val->Integer = FromInt; break; case TypeInt: DestValue->Val->Integer = FromInt; break;
case TypeShort: DestValue->Val->ShortInteger = (short)FromInt; break; case TypeShort: DestValue->Val->ShortInteger = (short)FromInt; break;
case TypeChar: DestValue->Val->Character = (unsigned char)FromInt; break; case TypeChar: DestValue->Val->Character = (char)FromInt; break;
case TypeLong: DestValue->Val->LongInteger = (long)FromInt; break; case TypeLong: DestValue->Val->LongInteger = (long)FromInt; break;
case TypeUnsignedInt: DestValue->Val->UnsignedInteger = (unsigned int)FromInt; break; case TypeUnsignedInt: DestValue->Val->UnsignedInteger = (unsigned int)FromInt; break;
case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)FromInt; break; case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)FromInt; break;
case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = (unsigned long)FromInt; break; case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = (unsigned long)FromInt; break;
case TypeUnsignedChar: DestValue->Val->UnsignedCharacter = (unsigned char)FromInt; break;
default: break; default: break;
} }
return Result; return Result;
@ -376,11 +400,12 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
{ {
case TypeInt: DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); break; case TypeInt: DestValue->Val->Integer = ExpressionCoerceInteger(SourceValue); break;
case TypeShort: DestValue->Val->ShortInteger = (short)ExpressionCoerceInteger(SourceValue); break; case TypeShort: DestValue->Val->ShortInteger = (short)ExpressionCoerceInteger(SourceValue); break;
case TypeChar: DestValue->Val->Character = (unsigned char)ExpressionCoerceUnsignedInteger(SourceValue); break; case TypeChar: DestValue->Val->Character = (char)ExpressionCoerceInteger(SourceValue); break;
case TypeLong: DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); break; case TypeLong: DestValue->Val->LongInteger = ExpressionCoerceInteger(SourceValue); break;
case TypeUnsignedInt: DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); break; case TypeUnsignedInt: DestValue->Val->UnsignedInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)ExpressionCoerceUnsignedInteger(SourceValue); break; case TypeUnsignedShort: DestValue->Val->UnsignedShortInteger = (unsigned short)ExpressionCoerceUnsignedInteger(SourceValue); break;
case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); break; case TypeUnsignedLong: DestValue->Val->UnsignedLongInteger = ExpressionCoerceUnsignedInteger(SourceValue); break;
case TypeUnsignedChar: DestValue->Val->UnsignedCharacter = (unsigned char)ExpressionCoerceUnsignedInteger(SourceValue); break;
#ifndef NO_FP #ifndef NO_FP
case TypeFP: case TypeFP:
@ -409,6 +434,29 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
} }
} }
/* char array = "abcd" */
if (DestValue->Typ->FromType->Base == TypeChar && SourceValue->Typ->Base == TypePointer && SourceValue->Typ->FromType->Base == TypeChar)
{
if (DestValue->Typ->ArraySize == 0) /* char x[] = "abcd", x is unsized */
{
int Size = strlen(SourceValue->Val->Pointer) + 1;
#ifdef DEBUG_ARRAY_INITIALIZER
PRINT_SOURCE_POS;
fprintf(stderr, "str size: %d\n", Size);
#endif
DestValue->Typ = TypeGetMatching(Parser->pc, Parser, DestValue->Typ->FromType, DestValue->Typ->Base, Size, DestValue->Typ->Identifier, TRUE);
VariableRealloc(Parser, DestValue, TypeSizeValue(DestValue, FALSE));
}
/* else, it's char x[10] = "abcd" */
#ifdef DEBUG_ARRAY_INITIALIZER
PRINT_SOURCE_POS;
fprintf(stderr, "char[%d] from char* (len=%d)\n", DestValue->Typ->ArraySize, strlen(SourceValue->Val->Pointer));
#endif
memcpy((void *)DestValue->Val, SourceValue->Val->Pointer, TypeSizeValue(DestValue, FALSE));
break;
}
if (DestValue->Typ != SourceValue->Typ) if (DestValue->Typ != SourceValue->Typ)
AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo); AssignFail(Parser, "%t from %t", DestValue->Typ, SourceValue->Typ, 0, 0, FuncName, ParamNo);
@ -508,6 +556,9 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
{ {
case TokenPlus: ResultFP = TopValue->Val->FP; break; case TokenPlus: ResultFP = TopValue->Val->FP; break;
case TokenMinus: ResultFP = -TopValue->Val->FP; break; case TokenMinus: ResultFP = -TopValue->Val->FP; break;
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
case TokenUnaryNot: ResultFP = !TopValue->Val->FP; break;
default: ProgramFail(Parser, "invalid operation"); break; default: ProgramFail(Parser, "invalid operation"); break;
} }
@ -567,6 +618,23 @@ void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack
void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue) void ExpressionPostfixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue)
{ {
debugf("ExpressionPostfixOperator()\n"); debugf("ExpressionPostfixOperator()\n");
#ifndef NO_FP
if (TopValue->Typ == &Parser->pc->FPType)
{
/* floating point prefix arithmetic */
double ResultFP = 0.0;
switch (Op)
{
case TokenIncrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP+1); break;
case TokenDecrement: ResultFP = ExpressionAssignFP(Parser, TopValue, TopValue->Val->FP-1); break;
default: ProgramFail(Parser, "invalid operation"); break;
}
ExpressionPushFP(Parser, StackTop, ResultFP);
}
else
#endif
if (IS_NUMERIC_COERCIBLE(TopValue)) if (IS_NUMERIC_COERCIBLE(TopValue))
{ {
long ResultInt = 0; long ResultInt = 0;
@ -861,7 +929,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
*StackTop = TopOperatorNode->Next; *StackTop = TopOperatorNode->Next;
/* do the prefix operation */ /* do the prefix operation */
if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence) if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */)
{ {
/* run the operator */ /* run the operator */
ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue); ExpressionPrefixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
@ -884,7 +952,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
*StackTop = TopStackNode->Next->Next; *StackTop = TopStackNode->Next->Next;
/* do the postfix operation */ /* do the postfix operation */
if (Parser->Mode == RunModeRun && FoundPrecedence < *IgnorePrecedence) if (Parser->Mode == RunModeRun /* && FoundPrecedence < *IgnorePrecedence */)
{ {
/* run the operator */ /* run the operator */
ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue); ExpressionPostfixOperator(Parser, StackTop, TopOperatorNode->Op, TopValue);
@ -911,7 +979,7 @@ void ExpressionStackCollapse(struct ParseState *Parser, struct ExpressionStack *
*StackTop = TopOperatorNode->Next->Next; *StackTop = TopOperatorNode->Next->Next;
/* do the infix operation */ /* do the infix operation */
if (Parser->Mode == RunModeRun && FoundPrecedence <= *IgnorePrecedence) if (Parser->Mode == RunModeRun /* && FoundPrecedence <= *IgnorePrecedence */)
{ {
/* run the operator */ /* run the operator */
ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue); ExpressionInfixOperator(Parser, StackTop, TopOperatorNode->Op, BottomValue, TopValue);
@ -982,7 +1050,7 @@ void ExpressionGetStructElement(struct ParseState *Parser, struct ExpressionStac
struct Value *StructVal = ParamVal; struct Value *StructVal = ParamVal;
struct ValueType *StructType = ParamVal->Typ; struct ValueType *StructType = ParamVal->Typ;
char *DerefDataLoc = (char *)ParamVal->Val; char *DerefDataLoc = (char *)ParamVal->Val;
struct Value *MemberValue; struct Value *MemberValue = NULL;
struct Value *Result; struct Value *Result;
/* if we're doing '->' dereference the struct pointer first */ /* if we're doing '->' dereference the struct pointer first */
@ -1044,7 +1112,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
{ {
/* it's either a new bracket level or a cast */ /* it's either a new bracket level or a cast */
enum LexToken BracketToken = LexGetToken(Parser, &LexValue, FALSE); enum LexToken BracketToken = LexGetToken(Parser, &LexValue, FALSE);
if (IS_TYPE_TOKEN(BracketToken) && (StackTop == NULL || StackTop->Op != TokenSizeof) ) if (IsTypeToken(Parser, BracketToken, LexValue) && (StackTop == NULL || StackTop->Op != TokenSizeof) )
{ {
/* it's a cast - get the new type */ /* it's a cast - get the new type */
struct ValueType *CastType; struct ValueType *CastType;
@ -1073,8 +1141,22 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
else else
{ {
/* scan and collapse the stack to the precedence of this operator, then push */ /* scan and collapse the stack to the precedence of this operator, then push */
/* take some extra care for double prefix operators, e.g. x = - -5, or x = **y */
int NextToken = LexGetToken(Parser, NULL, FALSE);
int TempPrecedenceBoost = 0;
if (NextToken > TokenComma && NextToken < TokenOpenBracket)
{
int NextPrecedence = OperatorPrecedence[(int)NextToken].PrefixPrecedence;
/* two prefix operators with equal precedence? make sure the innermost one runs first */
/* XXX - probably not correct, but can't find a test that fails at this */
if (LocalPrecedence == NextPrecedence)
TempPrecedenceBoost = -1;
}
ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence); ExpressionStackCollapse(Parser, &StackTop, Precedence, &IgnorePrecedence);
ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence); ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence + TempPrecedenceBoost);
} }
} }
else else
@ -1170,7 +1252,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
} }
else else
{ {
if (Parser->Mode == RunModeRun && Precedence < IgnorePrecedence) if (Parser->Mode == RunModeRun /* && Precedence < IgnorePrecedence */)
{ {
struct Value *VariableValue = NULL; struct Value *VariableValue = NULL;
@ -1215,7 +1297,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
PrefixState = FALSE; PrefixState = FALSE;
ExpressionStackPushValue(Parser, &StackTop, LexValue); ExpressionStackPushValue(Parser, &StackTop, LexValue);
} }
else if (IS_TYPE_TOKEN(Token)) else if (IsTypeToken(Parser, Token, LexValue))
{ {
/* it's a type. push it on the stack like a value. this is used in sizeof() */ /* it's a type. push it on the stack like a value. this is used in sizeof() */
struct ValueType *Typ; struct ValueType *Typ;
@ -1357,7 +1439,7 @@ void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt) void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName, int RunIt)
{ {
struct Value *ReturnValue = NULL; struct Value *ReturnValue = NULL;
struct Value *FuncValue; struct Value *FuncValue = NULL;
struct Value *Param; struct Value *Param;
struct Value **ParamArray = NULL; struct Value **ParamArray = NULL;
int ArgCount; int ArgCount;
@ -1440,6 +1522,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
/* run a user-defined function */ /* run a user-defined function */
struct ParseState FuncParser; struct ParseState FuncParser;
int Count; int Count;
int OldScopeID = Parser->ScopeID;
if (FuncValue->Val->FuncDef.Body.Pos == NULL) if (FuncValue->Val->FuncDef.Body.Pos == NULL)
ProgramFail(Parser, "'%s' is undefined", FuncName); ProgramFail(Parser, "'%s' is undefined", FuncName);
@ -1448,9 +1531,15 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
VariableStackFrameAdd(Parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); VariableStackFrameAdd(Parser, FuncName, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
Parser->pc->TopStackFrame->NumParams = ArgCount; Parser->pc->TopStackFrame->NumParams = ArgCount;
Parser->pc->TopStackFrame->ReturnValue = ReturnValue; Parser->pc->TopStackFrame->ReturnValue = ReturnValue;
/* Function parameters should not go out of scope */
Parser->ScopeID = -1;
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++) for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
VariableDefine(Parser->pc, Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE); VariableDefine(Parser->pc, Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count], NULL, TRUE);
Parser->ScopeID = OldScopeID;
if (ParseStatement(&FuncParser, TRUE) != ParseResultOk) if (ParseStatement(&FuncParser, TRUE) != ParseResultOk)
ProgramFail(&FuncParser, "function body expected"); ProgramFail(&FuncParser, "function body expected");

View file

@ -26,6 +26,10 @@
#define GETS_BUF_MAX 256 #define GETS_BUF_MAX 256
/* for debugging */
#define PRINT_SOURCE_POS ({ PrintSourceTextErrorLine(Parser->pc->CStdOut, Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos); PlatformPrintf(Parser->pc->CStdOut, "\n"); })
#define PRINT_TYPE(typ) PlatformPrintf(Parser->pc->CStdOut, "%t\n", typ);
/* small processors use a simplified FILE * for stdio, otherwise use the system FILE * */ /* small processors use a simplified FILE * for stdio, otherwise use the system FILE * */
#ifdef BUILTIN_MINI_STDLIB #ifdef BUILTIN_MINI_STDLIB
typedef struct OutputStream IOFILE; typedef struct OutputStream IOFILE;
@ -123,6 +127,7 @@ struct ParseState
short int HashIfLevel; /* how many "if"s we're nested down */ short int HashIfLevel; /* how many "if"s we're nested down */
short int HashIfEvaluateToLevel; /* if we're not evaluating an if branch, what the last evaluated level was */ short int HashIfEvaluateToLevel; /* if we're not evaluating an if branch, what the last evaluated level was */
char DebugMode; /* debugging mode */ char DebugMode; /* debugging mode */
int ScopeID; /* for keeping track of local variables (free them after they go out of scope) */
}; };
/* values */ /* values */
@ -131,10 +136,11 @@ enum BaseType
TypeVoid, /* no type */ TypeVoid, /* no type */
TypeInt, /* integer */ TypeInt, /* integer */
TypeShort, /* short integer */ TypeShort, /* short integer */
TypeChar, /* a single character (unsigned) */ TypeChar, /* a single character (signed) */
TypeLong, /* long integer */ TypeLong, /* long integer */
TypeUnsignedInt, /* unsigned integer */ TypeUnsignedInt, /* unsigned integer */
TypeUnsignedShort, /* unsigned short integer */ TypeUnsignedShort, /* unsigned short integer */
TypeUnsignedChar, /* unsigned 8-bit number */ /* must be before unsigned long */
TypeUnsignedLong, /* unsigned long integer */ TypeUnsignedLong, /* unsigned long integer */
#ifndef NO_FP #ifndef NO_FP
TypeFP, /* floating point */ TypeFP, /* floating point */
@ -189,13 +195,14 @@ struct MacroDef
/* values */ /* values */
union AnyValue union AnyValue
{ {
unsigned char Character; char Character;
short ShortInteger; short ShortInteger;
int Integer; int Integer;
long LongInteger; long LongInteger;
unsigned short UnsignedShortInteger; unsigned short UnsignedShortInteger;
unsigned int UnsignedInteger; unsigned int UnsignedInteger;
unsigned long UnsignedLongInteger; unsigned long UnsignedLongInteger;
unsigned char UnsignedCharacter;
char *Identifier; char *Identifier;
char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */ char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */
struct ValueType *Typ; struct ValueType *Typ;
@ -216,6 +223,8 @@ struct Value
char ValOnStack; /* the AnyValue is on the stack along with this Value */ char ValOnStack; /* the AnyValue is on the stack along with this Value */
char AnyValOnHeap; /* the AnyValue is separately allocated from the Value on the heap */ char AnyValOnHeap; /* the AnyValue is separately allocated from the Value on the heap */
char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */ char IsLValue; /* is modifiable and is allocated somewhere we can usefully modify it */
int ScopeID; /* to know when it goes out of scope */
char OutOfScope;
}; };
/* hash table data structure */ /* hash table data structure */
@ -414,6 +423,7 @@ struct Picoc_Struct
struct ValueType UnsignedIntType; struct ValueType UnsignedIntType;
struct ValueType UnsignedShortType; struct ValueType UnsignedShortType;
struct ValueType UnsignedLongType; struct ValueType UnsignedLongType;
struct ValueType UnsignedCharType;
#ifndef NO_FP #ifndef NO_FP
struct ValueType FPType; struct ValueType FPType;
#endif #endif
@ -543,6 +553,7 @@ struct Value *VariableAllocValueShared(struct ParseState *Parser, struct Value *
struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable); struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable);
struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit); struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit);
int VariableDefined(Picoc *pc, const char *Ident); int VariableDefined(Picoc *pc, const char *Ident);
int VariableDefinedAndOutOfScope(Picoc *pc, const char *Ident);
void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int NewSize); void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int NewSize);
void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct Value **LVal); void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct Value **LVal);
void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable); void VariableDefinePlatformVar(Picoc *pc, struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable);
@ -551,6 +562,8 @@ void VariableStackFramePop(struct ParseState *Parser);
struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident); struct Value *VariableStringLiteralGet(Picoc *pc, char *Ident);
void VariableStringLiteralDefine(Picoc *pc, char *Ident, struct Value *Val); void VariableStringLiteralDefine(Picoc *pc, char *Ident, struct Value *Val);
void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue); void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue);
int VariableScopeBegin(struct ParseState * Parser, int* PrevScopeID);
void VariableScopeEnd(struct ParseState * Parser, int ScopeID, int PrevScopeID);
/* clibrary.c */ /* clibrary.c */
void BasicIOInit(Picoc *pc); void BasicIOInit(Picoc *pc);

100
lex.c
View file

@ -129,13 +129,18 @@ enum LexToken LexCheckReservedWord(Picoc *pc, const char *Word)
/* get a numeric literal - used while scanning */ /* get a numeric literal - used while scanning */
enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Value) enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Value)
{ {
int Result = 0; long Result = 0;
int Base = 10; long Base = 10;
enum LexToken ResultToken; enum LexToken ResultToken;
#ifndef NO_FP #ifndef NO_FP
double FPResult; double FPResult;
double FPDiv; double FPDiv;
#endif #endif
/* long/unsigned flags */
#if 0 /* unused for now */
char IsLong = 0;
char IsUnsigned = 0;
#endif
if (*Lexer->Pos == '0') if (*Lexer->Pos == '0')
{ {
@ -156,45 +161,56 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer)) for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer))
Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos); Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos);
if (Result >= 0 && Result <= MAX_CHAR_VALUE) if (*Lexer->Pos == 'u' || *Lexer->Pos == 'U')
{ {
Value->Typ = &pc->CharType; LEXER_INC(Lexer);
Value->Val->Character = Result; /* IsUnsigned = 1; */
ResultToken = TokenCharacterConstant;
} }
else if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L')
{ {
Value->Typ = &pc->IntType; LEXER_INC(Lexer);
Value->Val->Integer = Result; /* IsLong = 1; */
}
Value->Typ = &pc->LongType; /* ignored? */
Value->Val->LongInteger = Result;
ResultToken = TokenIntegerConstant; ResultToken = TokenIntegerConstant;
}
if (Lexer->Pos == Lexer->End) if (Lexer->Pos == Lexer->End)
return ResultToken; return ResultToken;
if (*Lexer->Pos == 'l' || *Lexer->Pos == 'L') #ifndef NO_FP
if (Lexer->Pos == Lexer->End)
{ {
LEXER_INC(Lexer);
return ResultToken; return ResultToken;
} }
#ifndef NO_FP if (*Lexer->Pos != '.' && *Lexer->Pos != 'e' && *Lexer->Pos != 'E')
if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.') {
return ResultToken; return ResultToken;
}
Value->Typ = &pc->FPType; Value->Typ = &pc->FPType;
FPResult = (double)Result;
if (*Lexer->Pos == '.')
{
LEXER_INC(Lexer); LEXER_INC(Lexer);
for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base) for (FPDiv = 1.0/Base; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base)
{
FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv; FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv;
}
}
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E')) if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E'))
{ {
double ExponentMultiplier = 1.0; int ExponentSign = 1;
LEXER_INC(Lexer); LEXER_INC(Lexer);
if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-') if (Lexer->Pos != Lexer->End && *Lexer->Pos == '-')
{ {
ExponentMultiplier = -1.0; ExponentSign = -1;
LEXER_INC(Lexer); LEXER_INC(Lexer);
} }
@ -205,11 +221,14 @@ enum LexToken LexGetNumber(Picoc *pc, struct LexState *Lexer, struct Value *Valu
LEXER_INC(Lexer); LEXER_INC(Lexer);
} }
FPResult *= pow((double)Base, (double)Result * ExponentMultiplier); FPResult *= pow((double)Base, (double)Result * ExponentSign);
} }
Value->Val->FP = FPResult; Value->Val->FP = FPResult;
if (*Lexer->Pos == 'f' || *Lexer->Pos == 'F')
LEXER_INC(Lexer);
return TokenFPConstant; return TokenFPConstant;
#else #else
return ResultToken; return ResultToken;
@ -496,7 +515,7 @@ int LexTokenSize(enum LexToken Token)
switch (Token) switch (Token)
{ {
case TokenIdentifier: case TokenStringConstant: return sizeof(char *); case TokenIdentifier: case TokenStringConstant: return sizeof(char *);
case TokenIntegerConstant: return sizeof(int); case TokenIntegerConstant: return sizeof(long);
case TokenCharacterConstant: return sizeof(unsigned char); case TokenCharacterConstant: return sizeof(unsigned char);
case TokenFPConstant: return sizeof(double); case TokenFPConstant: return sizeof(double);
default: return 0; default: return 0;
@ -699,7 +718,7 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value, in
{ {
case TokenStringConstant: pc->LexValue.Typ = pc->CharPtrType; break; case TokenStringConstant: pc->LexValue.Typ = pc->CharPtrType; break;
case TokenIdentifier: pc->LexValue.Typ = NULL; break; case TokenIdentifier: pc->LexValue.Typ = NULL; break;
case TokenIntegerConstant: pc->LexValue.Typ = &pc->IntType; break; case TokenIntegerConstant: pc->LexValue.Typ = &pc->LongType; break;
case TokenCharacterConstant: pc->LexValue.Typ = &pc->CharType; break; case TokenCharacterConstant: pc->LexValue.Typ = &pc->CharType; break;
#ifndef NO_FP #ifndef NO_FP
case TokenFPConstant: pc->LexValue.Typ = &pc->FPType; break; case TokenFPConstant: pc->LexValue.Typ = &pc->FPType; break;
@ -766,7 +785,7 @@ void LexHashIf(struct ParseState *Parser)
{ {
/* get symbol to check */ /* get symbol to check */
struct Value *IdentValue; struct Value *IdentValue;
struct Value *SavedValue; struct Value *SavedValue = NULL;
struct ParseState MacroParser; struct ParseState MacroParser;
enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE); enum LexToken Token = LexGetRawToken(Parser, &IdentValue, TRUE);
@ -783,7 +802,7 @@ void LexHashIf(struct ParseState *Parser)
Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE); Token = LexGetRawToken(&MacroParser, &IdentValue, TRUE);
} }
if (Token != TokenCharacterConstant) if (Token != TokenCharacterConstant && Token != TokenIntegerConstant)
ProgramFail(Parser, "value expected"); ProgramFail(Parser, "value expected");
/* is the identifier defined? */ /* is the identifier defined? */
@ -823,6 +842,43 @@ void LexHashEndif(struct ParseState *Parser)
Parser->HashIfEvaluateToLevel = Parser->HashIfLevel; Parser->HashIfEvaluateToLevel = Parser->HashIfLevel;
} }
#if 0 /* useful for debug */
void LexPrintToken(enum LexToken Token)
{
char* TokenNames[] = {
/* 0x00 */ "None",
/* 0x01 */ "Comma",
/* 0x02 */ "Assign", "AddAssign", "SubtractAssign", "MultiplyAssign", "DivideAssign", "ModulusAssign",
/* 0x08 */ "ShiftLeftAssign", "ShiftRightAssign", "ArithmeticAndAssign", "ArithmeticOrAssign", "ArithmeticExorAssign",
/* 0x0d */ "QuestionMark", "Colon",
/* 0x0f */ "LogicalOr",
/* 0x10 */ "LogicalAnd",
/* 0x11 */ "ArithmeticOr",
/* 0x12 */ "ArithmeticExor",
/* 0x13 */ "Ampersand",
/* 0x14 */ "Equal", "NotEqual",
/* 0x16 */ "LessThan", "GreaterThan", "LessEqual", "GreaterEqual",
/* 0x1a */ "ShiftLeft", "ShiftRight",
/* 0x1c */ "Plus", "Minus",
/* 0x1e */ "Asterisk", "Slash", "Modulus",
/* 0x21 */ "Increment", "Decrement", "UnaryNot", "UnaryExor", "Sizeof", "Cast",
/* 0x27 */ "LeftSquareBracket", "RightSquareBracket", "Dot", "Arrow",
/* 0x2b */ "OpenBracket", "CloseBracket",
/* 0x2d */ "Identifier", "IntegerConstant", "FPConstant", "StringConstant", "CharacterConstant",
/* 0x32 */ "Semicolon", "Ellipsis",
/* 0x34 */ "LeftBrace", "RightBrace",
/* 0x36 */ "IntType", "CharType", "FloatType", "DoubleType", "VoidType", "EnumType",
/* 0x3c */ "LongType", "SignedType", "ShortType", "StaticType", "AutoType", "RegisterType", "ExternType", "StructType", "UnionType", "UnsignedType", "Typedef",
/* 0x46 */ "Continue", "Do", "Else", "For", "Goto", "If", "While", "Break", "Switch", "Case", "Default", "Return",
/* 0x52 */ "HashDefine", "HashInclude", "HashIf", "HashIfdef", "HashIfndef", "HashElse", "HashEndif",
/* 0x59 */ "New", "Delete",
/* 0x5b */ "OpenMacroBracket",
/* 0x5c */ "EOF", "EndOfLine", "EndOfFunction"
};
printf("{%s}", TokenNames[Token]);
}
#endif
/* get the next token given a parser state, pre-processing as we go */ /* get the next token given a parser state, pre-processing as we go */
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos) enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos)
{ {

108
parse.c
View file

@ -183,22 +183,77 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
ParserCopy(&CountParser, Parser); ParserCopy(&CountParser, Parser);
NumElements = ParseArrayInitialiser(&CountParser, NewVariable, FALSE); NumElements = ParseArrayInitialiser(&CountParser, NewVariable, FALSE);
if (NewVariable->Typ->ArraySize == 0)
VariableRealloc(Parser, NewVariable, NumElements);
else if (NewVariable->Typ->ArraySize != NumElements) if (NewVariable->Typ->Base != TypeArray)
AssignFail(Parser, "from an array of size %d to one of size %d", NULL, NULL, NumElements, NewVariable->Typ->ArraySize, NULL, 0); AssignFail(Parser, "%t from array initializer", NewVariable->Typ, NULL, 0, 0, NULL, 0);
if (NewVariable->Typ->ArraySize == 0)
{
NewVariable->Typ = TypeGetMatching(Parser->pc, Parser, NewVariable->Typ->FromType, NewVariable->Typ->Base, NumElements, NewVariable->Typ->Identifier, TRUE);
VariableRealloc(Parser, NewVariable, TypeSizeValue(NewVariable, FALSE));
}
#ifdef DEBUG_ARRAY_INITIALIZER
PRINT_SOURCE_POS;
printf("array size: %d \n", NewVariable->Typ->ArraySize);
#endif
} }
/* parse the array initialiser */ /* parse the array initialiser */
Token = LexGetToken(Parser, NULL, FALSE); Token = LexGetToken(Parser, NULL, FALSE);
while (Token != TokenRightBrace) while (Token != TokenRightBrace)
{
if (LexGetToken(Parser, NULL, FALSE) == TokenLeftBrace)
{
/* this is a sub-array initialiser */
int SubArraySize = 0;
struct Value *SubArray = NewVariable;
if (Parser->Mode == RunModeRun && DoAssignment)
{
SubArraySize = TypeSize(NewVariable->Typ->FromType, NewVariable->Typ->FromType->ArraySize, TRUE);
SubArray = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + SubArraySize * ArrayIndex), TRUE, NewVariable);
#ifdef DEBUG_ARRAY_INITIALIZER
int FullArraySize = TypeSize(NewVariable->Typ, NewVariable->Typ->ArraySize, TRUE);
PRINT_SOURCE_POS;
PRINT_TYPE(NewVariable->Typ)
printf("[%d] subarray size: %d (full: %d,%d) \n", ArrayIndex, SubArraySize, FullArraySize, NewVariable->Typ->ArraySize);
#endif
if (ArrayIndex >= NewVariable->Typ->ArraySize)
ProgramFail(Parser, "too many array elements");
}
LexGetToken(Parser, NULL, TRUE);
ParseArrayInitialiser(Parser, SubArray, DoAssignment);
}
else
{ {
struct Value *ArrayElement = NULL; struct Value *ArrayElement = NULL;
if (Parser->Mode == RunModeRun && DoAssignment) if (Parser->Mode == RunModeRun && DoAssignment)
ArrayElement = VariableAllocValueFromExistingData(Parser, NewVariable->Typ->FromType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + TypeSize(NewVariable->Typ->FromType, 0, TRUE) * ArrayIndex), TRUE, NewVariable); {
struct ValueType * ElementType = NewVariable->Typ;
int TotalSize = 1;
int ElementSize = 0;
/* int x[3][3] = {1,2,3,4} => handle it just like int x[9] = {1,2,3,4} */
while (ElementType->Base == TypeArray)
{
TotalSize *= ElementType->ArraySize;
ElementType = ElementType->FromType;
/* char x[10][10] = {"abc", "def"} => assign "abc" to x[0], "def" to x[1] etc */
if (LexGetToken(Parser, NULL, FALSE) == TokenStringConstant && ElementType->FromType->Base == TypeChar)
break;
}
ElementSize = TypeSize(ElementType, ElementType->ArraySize, TRUE);
#ifdef DEBUG_ARRAY_INITIALIZER
PRINT_SOURCE_POS;
printf("[%d/%d] element size: %d (x%d) \n", ArrayIndex, TotalSize, ElementSize, ElementType->ArraySize);
#endif
if (ArrayIndex >= TotalSize)
ProgramFail(Parser, "too many array elements");
ArrayElement = VariableAllocValueFromExistingData(Parser, ElementType, (union AnyValue *)(&NewVariable->Val->ArrayMem[0] + ElementSize * ArrayIndex), TRUE, NewVariable);
}
/* this is a normal expression initialiser */
if (!ExpressionParse(Parser, &CValue)) if (!ExpressionParse(Parser, &CValue))
ProgramFail(Parser, "expression expected"); ProgramFail(Parser, "expression expected");
@ -208,6 +263,7 @@ int ParseArrayInitialiser(struct ParseState *Parser, struct Value *NewVariable,
VariableStackPop(Parser, CValue); VariableStackPop(Parser, CValue);
VariableStackPop(Parser, ArrayElement); VariableStackPop(Parser, ArrayElement);
} }
}
ArrayIndex++; ArrayIndex++;
@ -393,8 +449,11 @@ void ParseFor(struct ParseState *Parser)
struct ParseState PreIncrement; struct ParseState PreIncrement;
struct ParseState PreStatement; struct ParseState PreStatement;
struct ParseState After; struct ParseState After;
enum RunMode OldMode = Parser->Mode; enum RunMode OldMode = Parser->Mode;
int PrevScopeID = 0, ScopeID = VariableScopeBegin(Parser, &PrevScopeID);
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket) if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
ProgramFail(Parser, "'(' expected"); ProgramFail(Parser, "'(' expected");
@ -420,7 +479,7 @@ void ParseFor(struct ParseState *Parser)
if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk) if (ParseStatementMaybeRun(Parser, Condition, TRUE) != ParseResultOk)
ProgramFail(Parser, "statement expected"); ProgramFail(Parser, "statement expected");
if (Parser->Mode == RunModeContinue) if (Parser->Mode == RunModeContinue && OldMode == RunModeRun)
Parser->Mode = RunModeRun; Parser->Mode = RunModeRun;
ParserCopyPos(&After, Parser); ParserCopyPos(&After, Parser);
@ -449,12 +508,16 @@ void ParseFor(struct ParseState *Parser)
if (Parser->Mode == RunModeBreak && OldMode == RunModeRun) if (Parser->Mode == RunModeBreak && OldMode == RunModeRun)
Parser->Mode = RunModeRun; Parser->Mode = RunModeRun;
VariableScopeEnd(Parser, ScopeID, PrevScopeID);
ParserCopyPos(Parser, &After); ParserCopyPos(Parser, &After);
} }
/* parse a block of code and return what mode it returned in */ /* parse a block of code and return what mode it returned in */
enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition) enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition)
{ {
int PrevScopeID = 0, ScopeID = VariableScopeBegin(Parser, &PrevScopeID);
if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace) if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace)
ProgramFail(Parser, "'{' expected"); ProgramFail(Parser, "'{' expected");
@ -477,6 +540,8 @@ enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Cond
if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace) if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace)
ProgramFail(Parser, "'}' expected"); ProgramFail(Parser, "'}' expected");
VariableScopeEnd(Parser, ScopeID, PrevScopeID);
return Parser->Mode; return Parser->Mode;
} }
@ -548,6 +613,33 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
CheckTrailingSemicolon = FALSE; CheckTrailingSemicolon = FALSE;
break; break;
} }
#ifdef FEATURE_AUTO_DECLARE_VARIABLES
else /* new_identifier = something */
{ /* try to guess type and declare the variable based on assigned value */
if (NextToken == TokenAssign && !VariableDefinedAndOutOfScope(Parser->pc, LexerValue->Val->Identifier))
{
if (Parser->Mode == RunModeRun)
{
struct Value *CValue;
char* Identifier = LexerValue->Val->Identifier;
LexGetToken(Parser, NULL, TRUE);
if (!ExpressionParse(Parser, &CValue))
{
ProgramFail(Parser, "expected: expression");
}
#if 0
PRINT_SOURCE_POS;
PlatformPrintf(Parser->pc->CStdOut, "%t %s = %d;\n", CValue->Typ, Identifier, CValue->Val->Integer);
printf("%d\n", VariableDefined(Parser->pc, Identifier));
#endif
VariableDefine(Parser->pc, Parser, Identifier, CValue, CValue->Typ, TRUE);
break;
}
}
}
#endif
} }
/* else fallthrough to expression */ /* else fallthrough to expression */
/* no break */ /* no break */
@ -652,13 +744,9 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi
break; break;
case TokenFor: case TokenFor:
{
enum RunMode OldMode = Parser->Mode;
ParseFor(Parser); ParseFor(Parser);
Parser->Mode = OldMode;
CheckTrailingSemicolon = FALSE; CheckTrailingSemicolon = FALSE;
break; break;
}
case TokenSemicolon: case TokenSemicolon:
CheckTrailingSemicolon = FALSE; CheckTrailingSemicolon = FALSE;

View file

@ -171,7 +171,8 @@ void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType
if (FuncName != NULL) if (FuncName != NULL)
PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName); PlatformPrintf(Stream, " in argument %d of call to %s()", ParamNo, FuncName);
ProgramFail(Parser, NULL, ""); PlatformPrintf(Stream, "\n");
PlatformExit(Parser->pc, 1);
} }
/* exit lexing with a message */ /* exit lexing with a message */

View file

@ -43,5 +43,18 @@ int main()
printf("a=%d\n",a); printf("a=%d\n",a);
} }
printf("\nTest 4\n");
a = 0; c = 0;
for (c=0;c<10;c++)
{
printf("c=%d\n",c);
foo();
continue;
for (a = 0; a < 2; a++)
printf("a=%d\n",a);
printf("bar\n");
}
return 0; return 0;
} }

View file

@ -8,3 +8,25 @@ a=0
Test 3 Test 3
c=0 c=0
foo foo
Test 4
c=0
foo
c=1
foo
c=2
foo
c=3
foo
c=4
foo
c=5
foo
c=6
foo
c=7
foo
c=8
foo
c=9
foo

View file

@ -59,7 +59,7 @@ TESTS= 00_assignment.test \
62_float.test \ 62_float.test \
63_typedef.test \ 63_typedef.test \
64_double_prefix_op.test \ 64_double_prefix_op.test \
65_typeless.test \ #65_typeless.test \
include csmith/Makefile include csmith/Makefile

5
type.c
View file

@ -121,11 +121,12 @@ void TypeInit(Picoc *pc)
pc->UberType.DerivedTypeList = NULL; pc->UberType.DerivedTypeList = NULL;
TypeAddBaseType(pc, &pc->IntType, TypeInt, sizeof(int), IntAlignBytes); TypeAddBaseType(pc, &pc->IntType, TypeInt, sizeof(int), IntAlignBytes);
TypeAddBaseType(pc, &pc->ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x); TypeAddBaseType(pc, &pc->ShortType, TypeShort, sizeof(short), (char *)&sa.y - &sa.x);
TypeAddBaseType(pc, &pc->CharType, TypeChar, sizeof(unsigned char), (char *)&ca.y - &ca.x); TypeAddBaseType(pc, &pc->CharType, TypeChar, sizeof(char), (char *)&ca.y - &ca.x);
TypeAddBaseType(pc, &pc->LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x); TypeAddBaseType(pc, &pc->LongType, TypeLong, sizeof(long), (char *)&la.y - &la.x);
TypeAddBaseType(pc, &pc->UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes); TypeAddBaseType(pc, &pc->UnsignedIntType, TypeUnsignedInt, sizeof(unsigned int), IntAlignBytes);
TypeAddBaseType(pc, &pc->UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x); TypeAddBaseType(pc, &pc->UnsignedShortType, TypeUnsignedShort, sizeof(unsigned short), (char *)&sa.y - &sa.x);
TypeAddBaseType(pc, &pc->UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x); TypeAddBaseType(pc, &pc->UnsignedLongType, TypeUnsignedLong, sizeof(unsigned long), (char *)&la.y - &la.x);
TypeAddBaseType(pc, &pc->UnsignedCharType, TypeUnsignedChar, sizeof(unsigned char), (char *)&ca.y - &ca.x);
TypeAddBaseType(pc, &pc->VoidType, TypeVoid, 0, 1); TypeAddBaseType(pc, &pc->VoidType, TypeVoid, 0, 1);
TypeAddBaseType(pc, &pc->FunctionType, TypeFunction, sizeof(int), IntAlignBytes); TypeAddBaseType(pc, &pc->FunctionType, TypeFunction, sizeof(int), IntAlignBytes);
TypeAddBaseType(pc, &pc->MacroType, TypeMacro, sizeof(int), IntAlignBytes); TypeAddBaseType(pc, &pc->MacroType, TypeMacro, sizeof(int), IntAlignBytes);
@ -394,7 +395,7 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ, int *IsSta
{ {
case TokenIntType: *Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType; break; case TokenIntType: *Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType; break;
case TokenShortType: *Typ = Unsigned ? &pc->UnsignedShortType : &pc->ShortType; break; case TokenShortType: *Typ = Unsigned ? &pc->UnsignedShortType : &pc->ShortType; break;
case TokenCharType: *Typ = &pc->CharType; break; case TokenCharType: *Typ = Unsigned ? &pc->UnsignedCharType : &pc->CharType; break;
case TokenLongType: *Typ = Unsigned ? &pc->UnsignedLongType : &pc->LongType; break; case TokenLongType: *Typ = Unsigned ? &pc->UnsignedLongType : &pc->LongType; break;
#ifndef NO_FP #ifndef NO_FP
case TokenFloatType: case TokenDoubleType: *Typ = &pc->FPType; break; case TokenFloatType: case TokenDoubleType: *Typ = &pc->FPType; break;

View file

@ -95,6 +95,10 @@ struct Value *VariableAllocValueAndData(Picoc *pc, struct ParseState *Parser, in
NewValue->ValOnStack = !OnHeap; NewValue->ValOnStack = !OnHeap;
NewValue->IsLValue = IsLValue; NewValue->IsLValue = IsLValue;
NewValue->LValueFrom = LValueFrom; NewValue->LValueFrom = LValueFrom;
if (Parser)
NewValue->ScopeID = Parser->ScopeID;
NewValue->OutOfScope = 0;
return NewValue; return NewValue;
} }
@ -158,10 +162,109 @@ void VariableRealloc(struct ParseState *Parser, struct Value *FromValue, int New
FromValue->AnyValOnHeap = TRUE; FromValue->AnyValOnHeap = TRUE;
} }
int VariableScopeBegin(struct ParseState * Parser, int* OldScopeID)
{
struct TableEntry *Entry;
struct TableEntry *NextEntry;
Picoc * pc = Parser->pc;
int Count;
#ifdef VAR_SCOPE_DEBUG
int FirstPrint = 0;
#endif
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
if (Parser->ScopeID == -1) return -1;
/* XXX dumb hash, let's hope for no collisions... */
*OldScopeID = Parser->ScopeID;
Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*));
/* or maybe a more human-readable hash for debugging? */
/* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
for (Count = 0; Count < HashTable->Size; Count++)
{
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
{
NextEntry = Entry->Next;
if (Entry->p.v.Val->ScopeID == Parser->ScopeID && Entry->p.v.Val->OutOfScope)
{
Entry->p.v.Val->OutOfScope = FALSE;
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key & ~1);
#ifdef VAR_SCOPE_DEBUG
if (!FirstPrint) { PRINT_SOURCE_POS; }
FirstPrint = 1;
printf(">>> back into scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
#endif
}
}
}
return Parser->ScopeID;
}
void VariableScopeEnd(struct ParseState * Parser, int ScopeID, int PrevScopeID)
{
struct TableEntry *Entry;
struct TableEntry *NextEntry;
Picoc * pc = Parser->pc;
int Count;
#ifdef VAR_SCOPE_DEBUG
int FirstPrint = 0;
#endif
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
if (ScopeID == -1) return;
for (Count = 0; Count < HashTable->Size; Count++)
{
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = NextEntry)
{
NextEntry = Entry->Next;
if (Entry->p.v.Val->ScopeID == ScopeID && !Entry->p.v.Val->OutOfScope)
{
#ifdef VAR_SCOPE_DEBUG
if (!FirstPrint) { PRINT_SOURCE_POS; }
FirstPrint = 1;
printf(">>> out of scope: %s %x %d\n", Entry->p.v.Key, Entry->p.v.Val->ScopeID, Entry->p.v.Val->Val->Integer);
#endif
Entry->p.v.Val->OutOfScope = TRUE;
Entry->p.v.Key = (char*)((intptr_t)Entry->p.v.Key | 1); /* alter the key so it won't be found by normal searches */
}
}
}
Parser->ScopeID = PrevScopeID;
}
int VariableDefinedAndOutOfScope(Picoc * pc, const char* Ident)
{
struct TableEntry *Entry;
int Count;
struct Table * HashTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
for (Count = 0; Count < HashTable->Size; Count++)
{
for (Entry = HashTable->HashTable[Count]; Entry != NULL; Entry = Entry->Next)
{
if (Entry->p.v.Val->OutOfScope && (char*)((intptr_t)Entry->p.v.Key & ~1) == Ident)
return TRUE;
}
}
return FALSE;
}
/* define a variable. Ident must be registered */ /* define a variable. Ident must be registered */
struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable) struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable)
{ {
struct Value *AssignValue; struct Value * AssignValue;
struct Table * currentTable = (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable;
int ScopeID = Parser ? Parser->ScopeID : -1;
#ifdef VAR_SCOPE_DEBUG
if (Parser) fprintf(stderr, "def %s %x (%s:%d:%d)\n", Ident, ScopeID, Parser->FileName, Parser->Line, Parser->CharacterPos);
#endif
if (InitValue != NULL) if (InitValue != NULL)
AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL); AssignValue = VariableAllocValueAndCopy(pc, Parser, InitValue, pc->TopStackFrame == NULL);
@ -169,8 +272,10 @@ struct Value *VariableDefine(Picoc *pc, struct ParseState *Parser, char *Ident,
AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable, NULL, pc->TopStackFrame == NULL); AssignValue = VariableAllocValueFromType(pc, Parser, Typ, MakeWritable, NULL, pc->TopStackFrame == NULL);
AssignValue->IsLValue = MakeWritable; AssignValue->IsLValue = MakeWritable;
AssignValue->ScopeID = ScopeID;
AssignValue->OutOfScope = FALSE;
if (!TableSet(pc, (pc->TopStackFrame == NULL) ? &(pc->GlobalTable) : &(pc->TopStackFrame)->LocalTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) if (!TableSet(pc, currentTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0))
ProgramFail(Parser, "'%s' is already defined", Ident); ProgramFail(Parser, "'%s' is already defined", Ident);
return AssignValue; return AssignValue;
@ -257,8 +362,13 @@ void VariableGet(Picoc *pc, struct ParseState *Parser, const char *Ident, struct
if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL)) if (pc->TopStackFrame == NULL || !TableGet(&pc->TopStackFrame->LocalTable, Ident, LVal, NULL, NULL, NULL))
{ {
if (!TableGet(&pc->GlobalTable, Ident, LVal, NULL, NULL, NULL)) if (!TableGet(&pc->GlobalTable, Ident, LVal, NULL, NULL, NULL))
{
if (VariableDefinedAndOutOfScope(pc, Ident))
ProgramFail(Parser, "'%s' is out of scope", Ident);
else
ProgramFail(Parser, "'%s' is undefined", Ident); ProgramFail(Parser, "'%s' is undefined", Ident);
} }
}
} }
/* define a global variable shared with a platform global. Ident will be registered */ /* define a global variable shared with a platform global. Ident will be registered */