diff --git a/Makefile b/Makefile index 62647e1..db40e4f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-Wall -g -DDEBUG_HEAP +CFLAGS=-Wall -g LIBS=-lm TARGET = picoc diff --git a/heap.c b/heap.c index 63d8998..f98a7a8 100644 --- a/heap.c +++ b/heap.c @@ -66,6 +66,9 @@ void *HeapStackGetFreeSpace(int *MemAvailable) /* push a new stack frame on to the stack */ void HeapPushStackFrame() { +#ifdef DEBUG_HEAP + printf("Adding stack frame at 0x%lx\n", (unsigned long)StackTop); +#endif *(void **)StackTop = StackFrame; StackFrame = StackTop; StackTop += sizeof(void *); @@ -74,10 +77,13 @@ void HeapPushStackFrame() /* pop the current stack frame, freeing all memory in the frame. can return NULL */ int HeapPopStackFrame() { - if (*(void **)StackFrame == NULL) + if (*(void **)StackFrame != NULL) { StackTop = StackFrame; StackFrame = *(void **)StackFrame; +#ifdef DEBUG_HEAP + printf("Popping stack frame back to 0x%lx\n", (unsigned long)StackTop); +#endif return TRUE; } else @@ -97,7 +103,7 @@ void *HeapAlloc(int Size) if (Bucket < FREELIST_BUCKETS && FreeListBucket[Bucket] != NULL) { /* try to allocate from a freelist bucket first */ -#ifdef DEBUG_HEAP +#ifdef DEBUG_HEAP printf("allocating %d(%d) from bucket", Size, AllocSize); #endif NewMem = FreeListBucket[Bucket]; diff --git a/lex.c b/lex.c index af8fc20..fd86b47 100644 --- a/lex.c +++ b/lex.c @@ -402,7 +402,7 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I } else { - if (IncPos && Token != TokenEndOfLine) + if (IncPos && Token != TokenEOF) Parser->Pos++; } diff --git a/parse.c b/parse.c index c166fcf..9657ded 100644 --- a/parse.c +++ b/parse.c @@ -32,6 +32,12 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, int Res VariableGet(Parser, FuncName, &FuncValue); if (FuncValue->Typ->Base != TypeFunction) ProgramFail(Parser, "not a function - can't call"); + + *Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, ResultOnHeap); + if (FuncValue->Val->FuncDef.Intrinsic == NULL) + VariableStackFrameAdd(Parser); + else + HeapPushStackFrame(); } /* parse arguments */ @@ -43,7 +49,7 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, int Res ProgramFail(Parser, "parameter %d to %s is the wrong type", ParameterUsed, FuncName); ParameterUsed++; - if (RunIt && ParameterUsed >= FuncValue->Val->FuncDef.NumParams) + if (RunIt && ParameterUsed > FuncValue->Val->FuncDef.NumParams) ProgramFail(Parser, "too many arguments"); Token = LexGetToken(Parser, NULL, TRUE); @@ -62,9 +68,6 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, int Res { /* run the function */ int Count; - VariableStackFrameAdd(Parser); - - *Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, ResultOnHeap); if (FuncValue->Val->FuncDef.Intrinsic == NULL) { /* run a user-defined function */ struct ParseState FuncParser = FuncValue->Val->FuncDef.Body; @@ -77,24 +80,26 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, int Res if (FuncValue->Val->FuncDef.ReturnType != (*Result)->Typ) ProgramFail(&FuncParser, "bad type of return value"); + + VariableStackFramePop(Parser); } else + { FuncValue->Val->FuncDef.Intrinsic(); - - VariableStackFramePop(Parser); - - for (Count = ParameterUsed-1; Count >= 0; Count--) /* free stack space used by parameters */ - VariableStackPop(Parser, Parameter[Count]); + HeapPopStackFrame(); + } } } /* parse a single value */ -int ParseValue(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, int RunIt) +int ParseValue(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, struct Value **LValue, int RunIt) { struct ParseState PreState = *Parser; struct Value *LexValue; int IntValue; enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE); + struct Value *LocalLValue = NULL; + int Success = TRUE; switch (Token) { @@ -136,27 +141,32 @@ int ParseValue(struct ParseState *Parser, struct Value **Result, int ResultOnHea { if (RunIt) { - struct Value *IdentValue; - VariableGet(Parser, LexValue->Val->String, &IdentValue); - if (IdentValue->Typ->Base == TypeMacro) + VariableGet(Parser, LexValue->Val->String, &LocalLValue); + if (LocalLValue->Typ->Base == TypeMacro) { - struct ParseState MacroLexer = IdentValue->Val->Parser; + struct ParseState MacroLexer = LocalLValue->Val->Parser; if (!ParseExpression(&MacroLexer, Result, ResultOnHeap, TRUE)) ProgramFail(&MacroLexer, "expression expected"); } - else if (!ISVALUETYPE(IdentValue->Typ)) + else if (!ISVALUETYPE(LocalLValue->Typ)) ProgramFail(Parser, "bad variable type"); + else + *Result = VariableAllocValueAndCopy(Parser, LocalLValue, ResultOnHeap); } } break; default: *Parser = PreState; - return FALSE; + Success = FALSE; + break; } - return TRUE; + if (LValue != NULL) + *LValue = LocalLValue; + + return Success; } struct Value *ParsePushFP(struct ParseState *Parser, int ResultOnHeap, double NewFP) @@ -178,8 +188,9 @@ int ParseExpression(struct ParseState *Parser, struct Value **Result, int Result { struct Value *CurrentValue; struct Value *TotalValue; + struct Value *LValue; - if (!ParseValue(Parser, &TotalValue, ResultOnHeap, RunIt)) + if (!ParseValue(Parser, &TotalValue, ResultOnHeap, &LValue, RunIt)) return FALSE; while (TRUE) @@ -202,16 +213,17 @@ int ParseExpression(struct ParseState *Parser, struct Value **Result, int Result if (RunIt) { - if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt) + if (CurrentValue->Typ->Base != TypeInt || LValue == NULL || LValue->Typ->Base != TypeInt) ProgramFail(Parser, "can't assign"); switch (Token) { - case TokenAddAssign: TotalValue->Val->Integer += CurrentValue->Val->Integer; break; - case TokenSubtractAssign: TotalValue->Val->Integer -= CurrentValue->Val->Integer; break; - default: TotalValue->Val->Integer = CurrentValue->Val->Integer; break; + case TokenAddAssign: LValue->Val->Integer += CurrentValue->Val->Integer; break; + case TokenSubtractAssign: LValue->Val->Integer -= CurrentValue->Val->Integer; break; + default: LValue->Val->Integer = CurrentValue->Val->Integer; break; } VariableStackPop(Parser, CurrentValue); + TotalValue->Val->Integer = LValue->Val->Integer; } // fallthrough @@ -221,7 +233,7 @@ int ParseExpression(struct ParseState *Parser, struct Value **Result, int Result return TRUE; } - if (!ParseValue(Parser, &CurrentValue, ResultOnHeap, RunIt)) + if (!ParseValue(Parser, &CurrentValue, ResultOnHeap, NULL, RunIt)) return FALSE; if (RunIt) diff --git a/table.c b/table.c index 7dad0bf..1f8ab32 100644 --- a/table.c +++ b/table.c @@ -32,7 +32,7 @@ void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int O static int TableSearch(struct Table *Tbl, const char *Key, int *AddAt) { struct TableEntry *Entry; - int HashValue = ((unsigned long)Key) % Tbl->Size; + int HashValue = ((unsigned long)Key) % Tbl->Size; /* shared strings have unique addresses so we don't need to hash them */ for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) { diff --git a/variable.c b/variable.c index 7d1ec8e..5c9a74a 100644 --- a/variable.c +++ b/variable.c @@ -30,6 +30,11 @@ void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap) if (NewValue == NULL) ProgramFail(Parser, "out of memory"); +#ifdef DEBUG_HEAP + if (!OnHeap) + printf("pushing %d at 0x%lx\n", Size, (unsigned long)NewValue); +#endif + return NewValue; } @@ -97,8 +102,13 @@ void VariableStackPop(struct ParseState *Parser, struct Value *Var) { int Success; +#ifdef DEBUG_HEAP + if (Var->ValOnStack) + printf("popping %d at 0x%lx\n", sizeof(struct Value) + Var->Typ->Sizeof, (unsigned long)Var); +#endif + if (Var->ValOnHeap) - { + { // XXX - is this a mismatch with allocation? HeapFree(Var->Val); Success = HeapPopStack(Var, sizeof(struct Value)); /* free from heap */ } @@ -130,7 +140,7 @@ void VariableStackFramePop(struct ParseState *Parser) if (TopStackFrame == NULL) ProgramFail(Parser, "stack is empty - can't go back"); - TopStackFrame = TopStackFrame->PreviousStackFrame; *Parser = TopStackFrame->ReturnParser; + TopStackFrame = TopStackFrame->PreviousStackFrame; HeapPopStackFrame(); }