mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-19 18:50:52 +00:00
add foreach v loop for maps
This commit is contained in:
parent
c58bd6efb5
commit
5cb0e3bc5b
3 changed files with 49 additions and 13 deletions
|
@ -11382,12 +11382,14 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxForEachLoop::FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* code, const FScriptPosition& pos)
|
FxForEachLoop::FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* arrayvar3, FxExpression* arrayvar4, FxExpression* code, const FScriptPosition& pos)
|
||||||
: FxLoopStatement(EFX_ForEachLoop, pos), loopVarName(vn), Array(arrayvar), Array2(arrayvar2), Code(code)
|
: FxLoopStatement(EFX_ForEachLoop, pos), loopVarName(vn), Array(arrayvar), Array2(arrayvar2), Array3(arrayvar3), Array4(arrayvar4), Code(code)
|
||||||
{
|
{
|
||||||
ValueType = TypeVoid;
|
ValueType = TypeVoid;
|
||||||
if (Array != nullptr) Array->NeedResult = false;
|
if (Array != nullptr) Array->NeedResult = false;
|
||||||
if (Array2 != nullptr) Array2->NeedResult = false;
|
if (Array2 != nullptr) Array2->NeedResult = false;
|
||||||
|
if (Array3 != nullptr) Array3->NeedResult = false;
|
||||||
|
if (Array4 != nullptr) Array4->NeedResult = false;
|
||||||
if (Code != nullptr) Code->NeedResult = false;
|
if (Code != nullptr) Code->NeedResult = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11395,6 +11397,8 @@ FxForEachLoop::~FxForEachLoop()
|
||||||
{
|
{
|
||||||
SAFE_DELETE(Array);
|
SAFE_DELETE(Array);
|
||||||
SAFE_DELETE(Array2);
|
SAFE_DELETE(Array2);
|
||||||
|
SAFE_DELETE(Array3);
|
||||||
|
SAFE_DELETE(Array4);
|
||||||
SAFE_DELETE(Code);
|
SAFE_DELETE(Code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11403,6 +11407,16 @@ FxExpression* FxForEachLoop::DoResolve(FCompileContext& ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(Array, ctx);
|
SAFE_RESOLVE(Array, ctx);
|
||||||
SAFE_RESOLVE(Array2, ctx);
|
SAFE_RESOLVE(Array2, ctx);
|
||||||
|
SAFE_RESOLVE(Array3, ctx);
|
||||||
|
SAFE_RESOLVE(Array4, ctx);
|
||||||
|
|
||||||
|
if(Array->ValueType->isMap() || Array->ValueType->isMapIterator())
|
||||||
|
{
|
||||||
|
auto mapLoop = new FxMapForEachLoop(NAME_None, loopVarName, Array, Array2, Array3, Array4, Code, ScriptPosition);
|
||||||
|
Array = Array2 = Array3 = Array4 = Code = nullptr;
|
||||||
|
delete this;
|
||||||
|
return mapLoop->Resolve(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
// Instead of writing a new code generator for this, convert this into
|
// Instead of writing a new code generator for this, convert this into
|
||||||
//
|
//
|
||||||
|
@ -11488,18 +11502,29 @@ FxExpression *FxMapForEachLoop::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if(valueVarName == NAME_None)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "missing value for foreach( k, v : m )");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto keyType = is_iterator ? static_cast<PMapIterator*>(MapExpr->ValueType)->KeyType : static_cast<PMap*>(MapExpr->ValueType)->KeyType;
|
|
||||||
auto valType = is_iterator ? static_cast<PMapIterator*>(MapExpr->ValueType)->ValueType : static_cast<PMap*>(MapExpr->ValueType)->ValueType;
|
|
||||||
|
|
||||||
auto block = new FxCompoundStatement(ScriptPosition);
|
auto block = new FxCompoundStatement(ScriptPosition);
|
||||||
auto k = new FxLocalVariableDeclaration(keyType, keyVarName, nullptr, 0, ScriptPosition);
|
|
||||||
|
auto valType = is_iterator ? static_cast<PMapIterator*>(MapExpr->ValueType)->ValueType : static_cast<PMap*>(MapExpr->ValueType)->ValueType;
|
||||||
|
auto keyType = is_iterator ? static_cast<PMapIterator*>(MapExpr->ValueType)->KeyType : static_cast<PMap*>(MapExpr->ValueType)->KeyType;
|
||||||
|
|
||||||
auto v = new FxLocalVariableDeclaration(valType, valueVarName, nullptr, 0, ScriptPosition);
|
auto v = new FxLocalVariableDeclaration(valType, valueVarName, nullptr, 0, ScriptPosition);
|
||||||
|
|
||||||
block->Add(k);
|
|
||||||
block->Add(v);
|
block->Add(v);
|
||||||
|
|
||||||
|
if(keyVarName != NAME_None)
|
||||||
|
{
|
||||||
|
auto k = new FxLocalVariableDeclaration(keyType, keyVarName, nullptr, 0, ScriptPosition);
|
||||||
|
block->Add(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(MapExpr->ValueType->isMapIterator())
|
if(MapExpr->ValueType->isMapIterator())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -11517,7 +11542,11 @@ FxExpression *FxMapForEachLoop::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
auto inner_block = new FxCompoundStatement(ScriptPosition);
|
auto inner_block = new FxCompoundStatement(ScriptPosition);
|
||||||
|
|
||||||
inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr, "GetKey", {}, ScriptPosition), true));
|
if(keyVarName != NAME_None)
|
||||||
|
{
|
||||||
|
inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr, "GetKey", {}, ScriptPosition), true));
|
||||||
|
}
|
||||||
|
|
||||||
inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr2, "GetValue", {}, ScriptPosition), true));
|
inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(MapExpr2, "GetValue", {}, ScriptPosition), true));
|
||||||
inner_block->Add(Code);
|
inner_block->Add(Code);
|
||||||
|
|
||||||
|
@ -11556,7 +11585,10 @@ FxExpression *FxMapForEachLoop::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
auto inner_block = new FxCompoundStatement(ScriptPosition);
|
auto inner_block = new FxCompoundStatement(ScriptPosition);
|
||||||
|
|
||||||
inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetKey", {}, ScriptPosition), true));
|
if(keyVarName != NAME_None)
|
||||||
|
{
|
||||||
|
inner_block->Add(new FxAssign(new FxIdentifier(keyVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetKey", {}, ScriptPosition), true));
|
||||||
|
}
|
||||||
inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetValue", {}, ScriptPosition), true));
|
inner_block->Add(new FxAssign(new FxIdentifier(valueVarName, ScriptPosition), new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "GetValue", {}, ScriptPosition), true));
|
||||||
inner_block->Add(Code);
|
inner_block->Add(Code);
|
||||||
|
|
||||||
|
|
|
@ -2074,10 +2074,12 @@ class FxForEachLoop : public FxLoopStatement
|
||||||
FName loopVarName;
|
FName loopVarName;
|
||||||
FxExpression* Array;
|
FxExpression* Array;
|
||||||
FxExpression* Array2;
|
FxExpression* Array2;
|
||||||
|
FxExpression* Array3;
|
||||||
|
FxExpression* Array4;
|
||||||
FxExpression* Code;
|
FxExpression* Code;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* code, const FScriptPosition& pos);
|
FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* arrayvar3, FxExpression* arrayvar4, FxExpression* code, const FScriptPosition& pos);
|
||||||
~FxForEachLoop();
|
~FxForEachLoop();
|
||||||
FxExpression* DoResolve(FCompileContext&);
|
FxExpression* DoResolve(FCompileContext&);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3388,9 +3388,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute)
|
||||||
auto iter = static_cast<ZCC_ArrayIterationStmt*>(ast);
|
auto iter = static_cast<ZCC_ArrayIterationStmt*>(ast);
|
||||||
auto var = iter->ItName->Name;
|
auto var = iter->ItName->Name;
|
||||||
FxExpression* const itArray = ConvertNode(iter->ItArray);
|
FxExpression* const itArray = ConvertNode(iter->ItArray);
|
||||||
FxExpression* const itArray2 = ConvertNode(iter->ItArray); // the handler needs two copies of this - here's the easiest place to create them.
|
FxExpression* const itArray2 = ConvertNode(iter->ItArray);
|
||||||
|
FxExpression* const itArray3 = ConvertNode(iter->ItArray);
|
||||||
|
FxExpression* const itArray4 = ConvertNode(iter->ItArray); // the handler needs copies of this - here's the easiest place to create them.
|
||||||
FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement);
|
FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement);
|
||||||
return new FxForEachLoop(iter->ItName->Name, itArray, itArray2, body, *ast);
|
return new FxForEachLoop(iter->ItName->Name, itArray, itArray2, itArray3, itArray4, body, *ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
case AST_MapIterationStmt:
|
case AST_MapIterationStmt:
|
||||||
|
|
Loading…
Reference in a new issue