diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 48a5b3a..c4237aa 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -61,6 +61,18 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec) mData = new ValueItem[mDataSize]; } +ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, int size) + : mLocation(location), + mDecType(dec), + mBaseValue(nullptr), mOffset(0), + mDataSize(size) +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; +} + ConstexprInterpreter::Value::Value(const Value& value) : mLocation(value.mLocation), mDecType(value.mDecType), @@ -403,6 +415,9 @@ void ConstexprInterpreter::Value::Assign(const Value& v) case DT_TYPE_ARRAY: memcpy(GetAddr(), v.GetAddr(), mDecType->mSize); break; + case DT_TYPE_POINTER: + PutPtr(v.GetPtr()); + break; } } @@ -489,7 +504,7 @@ Expression* ConstexprInterpreter::Value::ToExpression(LinkerSection* dataSection ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* err, LinkerSection* dataSection) - : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()) + : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()), mHeap(nullptr) { } @@ -499,6 +514,25 @@ ConstexprInterpreter::~ConstexprInterpreter(void) } +ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size) +{ + Value* v = new Value(exp->mLocation, type, size); + mHeap->Push(v); + return v; +} + +void ConstexprInterpreter::DeleteValue(Value* v) +{ + int i = mHeap->IndexOf(v); + if (i >= 0) + { + delete v; + mHeap->Remove(i); + } + else + mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory"); +} + Expression* ConstexprInterpreter::EvalCall(Expression* exp) { mProcType = exp->mLeft->mDecType; @@ -542,8 +576,14 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) return exp; } + mHeap = new ExpandingArray(); + Execute(exp->mLeft->mDecValue->mValue); + if (mHeap->Size() > 0) + mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr"); + delete mHeap; + return mResult.ToExpression(mDataSection); } @@ -798,6 +838,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con break; case TK_MUL: return vl.GetPtr(); + case TK_NEW: + v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, vl.GetInt()))); + break; + case TK_DELETE: + DeleteValue(vl.GetPtr().mBaseValue); + break; default: mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); } @@ -825,6 +871,8 @@ ConstexprInterpreter::Value ConstexprInterpreter::REval(Expression* exp) ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, ConstexprInterpreter* caller) { + mHeap = caller->mHeap; + mProcType = exp->mLeft->mDecType; Expression* pex = exp->mRight; @@ -882,7 +930,10 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); } else + { Execute(exp->mLeft->mDecValue->mValue); + UnwindDestructStack(0); + } return mResult; } @@ -1063,7 +1114,14 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) switch (exp->mType) { case EX_SCOPE: - return Execute(exp->mLeft); + { + int ds = mDestructStack.Size(); + Flow f = Execute(exp->mLeft); + UnwindDestructStack(ds); + + return f; + } + case EX_RETURN: mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase); return FLOW_RETURN; @@ -1141,34 +1199,53 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) } case EX_WHILE: + { + int ds = mDestructStack.Size(); while (REval(exp->mLeft).GetInt()) { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) break; } + UnwindDestructStack(ds); return FLOW_NEXT; + } case EX_DO: + { + int ds = mDestructStack.Size(); do { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) break; } while (REval(exp->mLeft).GetInt()); + UnwindDestructStack(ds); return FLOW_NEXT; + } case EX_FOR: + { + int ds = mDestructStack.Size(); if (exp->mLeft->mRight) Eval(exp->mLeft->mRight); while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt()) { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) @@ -1177,8 +1254,19 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) if (exp->mLeft->mLeft->mRight) Eval(exp->mLeft->mLeft->mRight); } + UnwindDestructStack(ds); return FLOW_NEXT; + } + + case EX_CONSTRUCT: + if (exp->mLeft->mLeft) + Eval(exp->mLeft->mLeft); + + if (exp->mLeft->mRight) + mDestructStack.Push(exp->mLeft->mRight); + + return Execute(exp->mRight); case EX_VOID: return FLOW_NEXT; @@ -1189,6 +1277,12 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) } } +void ConstexprInterpreter::UnwindDestructStack(int level) +{ + while (mDestructStack.Size() > level) + Eval(mDestructStack.Pop()); +} + ConstexprInterpreter::ValueItem::ValueItem(void) : mByte(0), mBaseValue(nullptr) { diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 8bb65b7..88f24e8 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -26,6 +26,7 @@ protected: Value(const Location& location); Value(Expression * exp); Value(const Location& location, Declaration * dec); + Value(const Location& location, Declaration* dec, int count); Value(const Value& value); Value(Value&& value); Value(Value * value, Declaration * type, int offset); @@ -70,6 +71,9 @@ protected: Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const; }; + Value * NewValue(Expression* exp, Declaration* type, int size); + void DeleteValue(Value* v); + Value EvalCall(Expression* exp, ConstexprInterpreter* caller); Value EvalBinary(Expression* exp, const Value& vl, const Value& vr); Value EvalUnary(Expression* exp, const Value& vl); @@ -89,11 +93,16 @@ protected: }; Flow Execute(Expression* exp); + void UnwindDestructStack(int level); Declaration* mProcType; Location mLocation; LinkerSection* mDataSection; GrowingArray mParams, mLocals; + ExpandingArray mDestructStack; + ExpandingArray * mHeap; + Errors * mErrors; Value mResult; + }; \ No newline at end of file diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 672710b..5864598 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -85,6 +85,8 @@ enum ErrorID EERR_FUNCTION_TEMPLATE, EERR_INVALID_CONSTEXPR, + EERR_DOUBLE_FREE, + EERR_UNBALANCED_HEAP_USE, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER,