- split up FxCompoundStatement into the old FxSequence and a new subclass. FxSequence is just a sequence of expressions, while FxCompoundStatement is the one that actually implements handling of local variables. The split was done so that ZCCCompiler::ConvertNode can return multiple statements as one object and for that FxCompoundStatement is not suitable.

- added conversion of local variable declarations. This is still untested
This commit is contained in:
Christoph Oelckers 2016-10-20 01:09:35 +02:00
parent 2d85efce2a
commit ffc38d422e
3 changed files with 112 additions and 38 deletions

View File

@ -5014,6 +5014,58 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build)
return v;
}
//==========================================================================
//
// FxSequence :: Resolve
//
//==========================================================================
FxExpression *FxSequence::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
for (unsigned i = 0; i < Expressions.Size(); ++i)
{
if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx)))
{
delete this;
return nullptr;
}
}
return this;
}
//==========================================================================
//
// FxSequence :: Emit
//
//==========================================================================
ExpEmit FxSequence::Emit(VMFunctionBuilder *build)
{
for (unsigned i = 0; i < Expressions.Size(); ++i)
{
ExpEmit v = Expressions[i]->Emit(build);
// Throw away any result. We don't care about it.
v.Free(build);
}
return ExpEmit();
}
//==========================================================================
//
// FxSequence :: GetDirectFunction
//
//==========================================================================
VMFunction *FxSequence::GetDirectFunction()
{
if (Expressions.Size() == 1)
{
return Expressions[0]->GetDirectFunction();
}
return NULL;
}
//==========================================================================
//
// FxCompoundStatement :: Resolve
@ -5023,18 +5075,11 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build)
FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
auto outer = ctx.Block;
Outer = ctx.Block;
ctx.Block = this;
for (unsigned i = 0; i < Expressions.Size(); ++i)
{
if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx)))
{
ctx.Block = Outer;
delete this;
return nullptr;
}
}
ctx.Block = Outer;
auto x = FxSequence::Resolve(ctx);
ctx.Block = outer;
return this;
}
@ -5046,33 +5091,13 @@ FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx)
ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build)
{
for (unsigned i = 0; i < Expressions.Size(); ++i)
{
ExpEmit v = Expressions[i]->Emit(build);
// Throw away any result. We don't care about it.
v.Free(build);
}
auto e = FxSequence::Emit(build);
// Release all local variables in this block.
for (auto l : LocalVars)
{
l->Release(build);
}
return ExpEmit();
}
//==========================================================================
//
// FxCompoundStatement :: GetDirectFunction
//
//==========================================================================
VMFunction *FxCompoundStatement::GetDirectFunction()
{
if (Expressions.Size() == 1)
{
return Expressions[0]->GetDirectFunction();
}
return NULL;
return e;
}
//==========================================================================

View File

@ -1087,25 +1087,41 @@ public:
//==========================================================================
//
// FxCompoundStatement
// FxSequence (a list of statements with no semantics attached - used to return multiple nodes as one)
//
//==========================================================================
class FxLocalVariableDeclaration;
class FxCompoundStatement : public FxExpression
class FxSequence : public FxExpression
{
TDeletingArray<FxExpression *> Expressions;
public:
FxSequence(const FScriptPosition &pos) : FxExpression(pos) {}
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); }
VMFunction *GetDirectFunction();
};
//==========================================================================
//
// FxCompoundStatement (like a list but implements maintenance of local variables)
//
//==========================================================================
class FxLocalVariableDeclaration;
class FxCompoundStatement : public FxSequence
{
TArray<FxLocalVariableDeclaration *> LocalVars;
TDeletingArray<FxExpression *> Expressions;
FxCompoundStatement *Outer = nullptr;
friend class FxLocalVariableDeclaration;
public:
FxCompoundStatement(const FScriptPosition &pos) : FxExpression(pos) {}
FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {}
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); }
VMFunction *GetDirectFunction();
FxLocalVariableDeclaration *FindLocalVariable(FName name);
bool CheckLocalVariable(FName name);
};

View File

@ -2534,6 +2534,39 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
return new FxConditional(condition, left, right);
}
case AST_LocalVarStmt:
{
auto loc = static_cast<ZCC_LocalVarStmt *>(ast);
auto node = loc->Vars;
FxSequence *list = new FxSequence(*ast);
do
{
// Type determination must be done for each field to properly handle array definitions.
PType *type = DetermineType(ConvertClass, node, node->Name, loc->Type, true, false);
if (type->IsKindOf(RUNTIME_CLASS(PArray)))
{
Error(loc, "Local array variables not implemented yet.");
}
else
{
FxExpression *val;
if (node->InitIsArray)
{
Error(node, "Tried to initialize %s with an array", FName(node->Name).GetChars());
val = nullptr;
}
else
{
val = node->Init ? ConvertNode(node->Init) : nullptr;
}
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, *node));
}
node = static_cast<decltype(node)>(node->SiblingNext);
} while (node != loc->Vars);
return list;
}
case AST_ExpressionStmt:
return ConvertNode(static_cast<ZCC_ExpressionStmt *>(ast)->Expression);