Took a first stab at implementing new/delete. Needs a bit more thought on how to handle dangling references to deallocated storage.
git-svn-id: http://picoc.googlecode.com/svn/trunk@211 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
188eb93d43
commit
1ab28fcfb7
1
TODO
1
TODO
|
@ -26,6 +26,7 @@ Improvements:
|
||||||
Need test/debug:
|
Need test/debug:
|
||||||
* all break/continue variations
|
* all break/continue variations
|
||||||
* getchar()/gets() tests
|
* getchar()/gets() tests
|
||||||
|
* new/delete heap allocation
|
||||||
|
|
||||||
Also:
|
Also:
|
||||||
* Remove Var parameter from HeapPopStack() once we're certain it all works
|
* Remove Var parameter from HeapPopStack() once we're certain it all works
|
||||||
|
|
15
expression.c
15
expression.c
|
@ -18,6 +18,7 @@ int ExpressionParseValue(struct ParseState *Parser, struct Value **Result)
|
||||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||||
struct Value *LocalLValue = NULL;
|
struct Value *LocalLValue = NULL;
|
||||||
struct ValueType *VType;
|
struct ValueType *VType;
|
||||||
|
char *Identifier;
|
||||||
int Success = TRUE;
|
int Success = TRUE;
|
||||||
|
|
||||||
switch (Token)
|
switch (Token)
|
||||||
|
@ -134,6 +135,20 @@ int ExpressionParseValue(struct ParseState *Parser, struct Value **Result)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TokenNew:
|
||||||
|
TypeParse(Parser, &VType, &Identifier);
|
||||||
|
if (Identifier != StrEmpty)
|
||||||
|
ProgramFail(Parser, "identifier not expected here");
|
||||||
|
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{ /* create an object of this type on the heap and a pointer to it on the stack */
|
||||||
|
LocalLValue = VariableAllocValueFromType(Parser, VType, TRUE, NULL);
|
||||||
|
*Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, VType, TypePointer, 0, StrEmpty), FALSE, NULL);
|
||||||
|
(*Result)->Val->Pointer.Segment = LocalLValue;
|
||||||
|
(*Result)->Val->Pointer.Offset = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*Parser = PreState;
|
*Parser = PreState;
|
||||||
Success = FALSE;
|
Success = FALSE;
|
||||||
|
|
1
lex.c
1
lex.c
|
@ -52,6 +52,7 @@ static struct ReservedWord ReservedWords[] =
|
||||||
{ "if", TokenIf, NULL },
|
{ "if", TokenIf, NULL },
|
||||||
{ "int", TokenIntType, NULL },
|
{ "int", TokenIntType, NULL },
|
||||||
{ "long", TokenLongType, NULL },
|
{ "long", TokenLongType, NULL },
|
||||||
|
{ "new", TokenNew, NULL },
|
||||||
{ "return", TokenReturn, NULL },
|
{ "return", TokenReturn, NULL },
|
||||||
// { "short", TokenShortType, NULL },
|
// { "short", TokenShortType, NULL },
|
||||||
{ "signed", TokenSignedType, NULL },
|
{ "signed", TokenSignedType, NULL },
|
||||||
|
|
39
parse.c
39
parse.c
|
@ -472,16 +472,43 @@ int ParseStatement(struct ParseState *Parser)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TokenDelete:
|
case TokenDelete:
|
||||||
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier)
|
{
|
||||||
ProgramFail(Parser, "identifier expected");
|
/* first try to parse this as "delete a pointer from an expression" */
|
||||||
|
struct ParseState PreExpression = *Parser;
|
||||||
|
int WasPointer = FALSE;
|
||||||
|
|
||||||
CValue = TableDelete(&GlobalTable, LexerValue->Val->Identifier);
|
if (ExpressionParse(Parser, &CValue))
|
||||||
|
{ /* found an expression */
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{
|
||||||
|
if (TopStackFrame->ReturnValue->Typ->Base == TypePointer)
|
||||||
|
{ /* this was a pointer to something - delete the object we're pointing to */
|
||||||
|
// XXX - now I'm having second thoughts about this
|
||||||
|
WasPointer = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (CValue == NULL)
|
VariableStackPop(Parser, CValue);
|
||||||
ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VariableFree(CValue);
|
if (!WasPointer)
|
||||||
|
{ /* go back and try it as a function or variable name to delete */
|
||||||
|
*Parser = PreExpression;
|
||||||
|
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier)
|
||||||
|
ProgramFail(Parser, "identifier expected");
|
||||||
|
|
||||||
|
if (Parser->Mode == RunModeRun)
|
||||||
|
{ /* delete this variable or function */
|
||||||
|
CValue = TableDelete(&GlobalTable, LexerValue->Val->Identifier);
|
||||||
|
|
||||||
|
if (CValue == NULL)
|
||||||
|
ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier);
|
||||||
|
|
||||||
|
VariableFree(CValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*Parser = PreState;
|
*Parser = PreState;
|
||||||
|
|
2
picoc.h
2
picoc.h
|
@ -54,7 +54,7 @@ enum LexToken
|
||||||
TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType,
|
TokenIntType, TokenCharType, TokenFloatType, TokenDoubleType, TokenVoidType, TokenEnumType,
|
||||||
TokenLongType, TokenSignedType, TokenShortType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef,
|
TokenLongType, TokenSignedType, TokenShortType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef,
|
||||||
TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn,
|
TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn,
|
||||||
TokenHashDefine, TokenHashInclude, TokenDelete,
|
TokenHashDefine, TokenHashInclude, TokenNew, TokenDelete,
|
||||||
TokenNone, TokenEOF, TokenEndOfLine, TokenEndOfFunction
|
TokenNone, TokenEOF, TokenEndOfLine, TokenEndOfFunction
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue