Skip to content

Commit

Permalink
add foreach(a/type a : thinkeriterator/actoriterator)
Browse files Browse the repository at this point in the history
  • Loading branch information
RicardoLuis0 committed Oct 15, 2023
1 parent 8863647 commit 0d4fad9
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/common/engine/namedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ xx(FQuat)
xx(let)
xx(BlockThingsIterator)
xx(BlockLinesIterator)
xx(ActorIterator)
xx(ThinkerIterator)

xx(Min)
xx(Max)
Expand Down
116 changes: 116 additions & 0 deletions src/common/scripting/backend/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11210,6 +11210,16 @@ FxExpression* FxForEachLoop::DoResolve(FCompileContext& ctx)
delete this;
return blockIt->Resolve(ctx);
}
else if(Array->ValueType->isObjectPointer() && (((PObjectPointer*)Array->ValueType)->PointedClass()->TypeName == NAME_ActorIterator || ((PObjectPointer*)Array->ValueType)->PointedClass()->TypeName == NAME_ThinkerIterator))
{
auto castIt = new FxCastForEachLoop(NAME_None, loopVarName, Array, Code, ScriptPosition);
delete Array2;
delete Array3;
delete Array4;
Array = Array2 = Array3 = Array4 = Code = nullptr;
delete this;
return castIt->Resolve(ctx);
}

// Instead of writing a new code generator for this, convert this into
//
Expand Down Expand Up @@ -11522,6 +11532,112 @@ FxExpression *FxBlockIteratorForEachLoop::Resolve(FCompileContext &ctx)
return block->Resolve(ctx);
}

//==========================================================================
//
// FxCastForEachLoop
//
//==========================================================================

FxCastForEachLoop::FxCastForEachLoop(FName cv, FName vv, FxExpression* castiteartorexpr, FxExpression* code, const FScriptPosition& pos)
: FxExpression(EFX_BlockForEachLoop, pos), castClassName(cv), varVarName(vv), CastIteratorExpr(castiteartorexpr), Code(code)
{
ValueType = TypeVoid;
if (CastIteratorExpr != nullptr) CastIteratorExpr->NeedResult = false;
if (Code != nullptr) Code->NeedResult = false;
}

FxCastForEachLoop::~FxCastForEachLoop()
{
SAFE_DELETE(CastIteratorExpr);
SAFE_DELETE(Code);
}

FxExpression *FxCastForEachLoop::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(CastIteratorExpr, ctx);

if(!(CastIteratorExpr->ValueType->isObjectPointer()))
{
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be an actor or thinker iterator, but is a %s",CastIteratorExpr->ValueType->DescriptiveName());
delete this;
return nullptr;
}
else if(varVarName == NAME_None)
{
ScriptPosition.Message(MSG_ERROR, "missing var for foreach(Type var : it )");
delete this;
return nullptr;
}

PType * varType = nullptr;
PClass * itType = ((PObjectPointer*)CastIteratorExpr->ValueType)->PointedClass();

FName fieldName = NAME_None;

if(itType->TypeName == NAME_ActorIterator)
{
fieldName = "Actor";
}
else if(itType->TypeName == NAME_ThinkerIterator)
{
fieldName = "Thinker";
}
else
{
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be an actor or thinker iterator, but is a %s",CastIteratorExpr->ValueType->DescriptiveName());
delete this;
return nullptr;
}

if(castClassName != NAME_None)
{
fieldName = castClassName;
}

PClass * varTypeClass = PClass::FindClass(fieldName);
varType = varTypeClass->VMType;

if(!varType)
{
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - could not find class '%s'",castClassName.GetChars());
delete this;
return nullptr;
}

varType = NewPointer(varType, false);

/*
{
CastType var;
ActorIterator|ThinkerIterator @it = expr;
while(var = CastType(@it.Next()))
body
}
*/

auto block = new FxCompoundStatement(ScriptPosition);

block->Add(new FxLocalVariableDeclaration(varType, varVarName, nullptr, 0, ScriptPosition));

block->Add(new FxLocalVariableDeclaration(CastIteratorExpr->ValueType, "@it", CastIteratorExpr, 0, ScriptPosition));

auto inner_block = new FxCompoundStatement(ScriptPosition);

FxExpression * nextCallCast = new FxMemberFunctionCall(new FxIdentifier("@it", ScriptPosition), "Next", {}, ScriptPosition);

if(castClassName != NAME_None)
{
nextCallCast = new FxDynamicCast(varTypeClass, nextCallCast);
}

block->Add(new FxWhileLoop(new FxAssign(new FxIdentifier(varVarName, ScriptPosition), nextCallCast), Code, ScriptPosition));

CastIteratorExpr = Code = nullptr;
delete this;
return block->Resolve(ctx);
}

//==========================================================================
//
// FxJumpStatement
Expand Down
21 changes: 21 additions & 0 deletions src/common/scripting/backend/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ enum EFxType
EFX_ForEachLoop,
EFX_MapForEachLoop,
EFX_BlockForEachLoop,
EFX_CastForEachLoop,
EFX_JumpStatement,
EFX_ReturnStatement,
EFX_ClassTypeCast,
Expand Down Expand Up @@ -2107,6 +2108,26 @@ class FxBlockIteratorForEachLoop : public FxExpression
//ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself
};

//==========================================================================
//
// FxCastForEachLoop
//
//==========================================================================

class FxCastForEachLoop : public FxExpression
{
FName castClassName;
FName varVarName;
FxExpression* CastIteratorExpr;
FxExpression* Code;

public:
FxCastForEachLoop(FName cv, FName vv, FxExpression* castiteartorexpr, FxExpression* code, const FScriptPosition& pos);
~FxCastForEachLoop();
FxExpression *Resolve(FCompileContext&);
//ExpEmit Emit(VMFunctionBuilder *build); This node is transformed, so it won't ever be emitted itself
};

//==========================================================================
//
// FxJumpStatement
Expand Down
16 changes: 16 additions & 0 deletions src/common/scripting/frontend/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,21 @@ static void PrintBlockIterationStmt(FLispString &out, const ZCC_TreeNode *node)
out.Close();
}

static void PrintCastIterationStmt(FLispString &out, const ZCC_TreeNode *node)
{
auto inode = (ZCC_CastIterationStmt *)node;
out.Break();
out.Open("cast-iteration-stmt");
PrintVarName(out, inode->ItCast);
out.Break();
PrintVarName(out, inode->ItVar);
out.Break();
PrintNodes(out, inode->ItIterator);
out.Break();
PrintNodes(out, inode->LoopStatement);
out.Close();
}

static const NodePrinterFunc TreeNodePrinter[] =
{
PrintIdentifier,
Expand Down Expand Up @@ -1084,6 +1099,7 @@ static const NodePrinterFunc TreeNodePrinter[] =
PrintArrayIterationStmt,
PrintMapIterationStmt,
PrintBlockIterationStmt,
PrintCastIterationStmt,
};

FString ZCC_PrintAST(const ZCC_TreeNode *root)
Expand Down
13 changes: 13 additions & 0 deletions src/common/scripting/frontend/zcc-parse.lemon
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,7 @@ statement(X) ::= iteration_statement(X).
statement(X) ::= array_iteration_statement(X).
statement(X) ::= map_iteration_statement(X).
statement(X) ::= block_iteration_statement(X).
statement(X) ::= cast_iteration_statement(X).
statement(X) ::= jump_statement(X).
statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= assign_decl_statement(A) SEMICOLON.{ X = A; /*X-overwrites-A*/ }
Expand Down Expand Up @@ -2152,6 +2153,18 @@ block_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(VAR) COMMA vari
X = iter;
}

%type cast_iteration_statement{ZCC_Statement *}

cast_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(CAST) variable_name(VAR) COLON expr(EX) RPAREN statement(ST).
{
NEW_AST_NODE(CastIterationStmt, iter, T);
iter->ItCast = CAST;
iter->ItVar = VAR;
iter->ItIterator = EX;
iter->LoopStatement = ST;
X = iter;
}

while_or_until(X) ::= WHILE(T).
{
X.Int = ZCC_WHILE;
Expand Down
10 changes: 10 additions & 0 deletions src/common/scripting/frontend/zcc_compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3413,6 +3413,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute)
return new FxBlockIteratorForEachLoop(var, pos, flags, itBlock, body, *ast);
}

case AST_CastIterationStmt:
{
auto iter = static_cast<ZCC_CastIterationStmt*>(ast);
auto cls = iter->ItCast->Name;
auto var = iter->ItVar->Name;
FxExpression* const itIterator = ConvertNode(iter->ItIterator);
FxExpression* const body = ConvertImplicitScopeNode(ast, iter->LoopStatement);
return new FxCastForEachLoop(cls, var, itIterator, body, *ast);
}

case AST_IterationStmt:
{
auto iter = static_cast<ZCC_IterationStmt *>(ast);
Expand Down
9 changes: 9 additions & 0 deletions src/common/scripting/frontend/zcc_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ enum EZCCTreeNodeType
AST_ArrayIterationStmt,
AST_MapIterationStmt,
AST_BlockIterationStmt,
AST_CastIterationStmt,

NUM_AST_NODE_TYPES
};
Expand Down Expand Up @@ -551,6 +552,14 @@ struct ZCC_BlockIterationStmt : ZCC_Statement
ZCC_Statement* LoopStatement;
};

struct ZCC_CastIterationStmt : ZCC_Statement
{
ZCC_VarName* ItCast;
ZCC_VarName* ItVar;
ZCC_Expression* ItIterator;
ZCC_Statement* LoopStatement;
};

struct ZCC_IfStmt : ZCC_Statement
{
ZCC_Expression *Condition;
Expand Down

0 comments on commit 0d4fad9

Please sign in to comment.