mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-16 09:31:14 +00:00
Implemented compound initializers for arrays.
This commit is contained in:
parent
ff9fe5f4d0
commit
541fd0097b
3 changed files with 186 additions and 6 deletions
|
@ -11166,7 +11166,7 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
auto sfunc = static_cast<VMScriptFunction *>(ctx.Function->Variants[0].Implementation);
|
||||
StackOffset = sfunc->AllocExtraStack(ValueType);
|
||||
// Todo: Process the compound initializer once implemented.
|
||||
|
||||
if (Init != nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars());
|
||||
|
@ -11408,3 +11408,161 @@ ExpEmit FxStaticArray::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
FxLocalArrayDeclaration::FxLocalArrayDeclaration(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos)
|
||||
: FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, 0, pos)
|
||||
{
|
||||
ElementType = type;
|
||||
ExprType = EFX_LocalArrayDeclaration;
|
||||
values = std::move(args);
|
||||
}
|
||||
|
||||
FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
for (unsigned int i = 0; i < values.Size(); i++)
|
||||
{
|
||||
auto v = values[i]->Resolve(ctx);
|
||||
if (v == nullptr)
|
||||
{
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
values[i] = v;
|
||||
}
|
||||
|
||||
if (ctx.Block == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto)
|
||||
{
|
||||
auto sfunc = static_cast<VMScriptFunction *>(ctx.Function->Variants[0].Implementation);
|
||||
StackOffset = sfunc->AllocExtraStack(ValueType);
|
||||
|
||||
if (Init != nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (ValueType != TypeAuto)
|
||||
{
|
||||
if (Init) Init = new FxTypeCast(Init, ValueType, false);
|
||||
SAFE_RESOLVE_OPT(Init, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Init == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Automatic type deduction requires an initializer for variable %s", Name.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
SAFE_RESOLVE_OPT(Init, ctx);
|
||||
if (Init->ValueType->RegType == REGT_NIL)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
ValueType = Init->ValueType;
|
||||
// check for undersized ints and floats. These are not allowed as local variables.
|
||||
if (IsInteger() && ValueType->Align < sizeof(int)) ValueType = TypeSInt32;
|
||||
else if (IsFloat() && ValueType->Align < sizeof(double)) ValueType = TypeFloat64;
|
||||
}
|
||||
if (Name != NAME_None)
|
||||
{
|
||||
for (auto l : ctx.Block->LocalVars)
|
||||
{
|
||||
if (l->Name == Name)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Local variable %s already defined", Name.GetChars());
|
||||
l->ScriptPosition.Message(MSG_ERROR, "Original definition is here ");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.Block->LocalVars.Push(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters.
|
||||
|
||||
auto arrOffsetReg = build->Registers[REGT_INT].Get(1);
|
||||
for (auto v : values)
|
||||
{
|
||||
ExpEmit emitval = v->Emit(build);
|
||||
|
||||
int regtype = emitval.RegType;
|
||||
if (regtype < REGT_INT || regtype > REGT_TYPE)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Attempted to assign a non-value");
|
||||
return ExpEmit();
|
||||
}
|
||||
if (emitval.Konst)
|
||||
{
|
||||
auto constval = static_cast<FxConstant *>(v);
|
||||
int regNum = build->Registers[regtype].Get(1);
|
||||
switch (regtype)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_LK, regNum, build->GetConstantInt(constval->GetValue().GetInt()));
|
||||
build->Emit(OP_SW_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_LKF, regNum, build->GetConstantInt(constval->GetValue().GetInt()));
|
||||
build->Emit(OP_SDP_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_LKP, regNum, build->GetConstantInt(constval->GetValue().GetInt()));
|
||||
build->Emit(OP_SP_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
break;
|
||||
case REGT_STRING:
|
||||
build->Emit(OP_LKS, regNum, build->GetConstantInt(constval->GetValue().GetInt()));
|
||||
build->Emit(OP_SS_R, build->FramePointer.RegNum, regNum, arrOffsetReg);
|
||||
break;
|
||||
}
|
||||
build->Emit(OP_ADD_RK, arrOffsetReg, arrOffsetReg, build->GetConstantInt(v->ValueType->Size));
|
||||
build->Registers[regtype].Return(regNum, 1);
|
||||
|
||||
emitval.Free(build);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (regtype)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_SW_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_SDP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_SP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
case REGT_STRING:
|
||||
build->Emit(OP_SS_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg);
|
||||
break;
|
||||
}
|
||||
build->Emit(OP_ADD_RK, arrOffsetReg, arrOffsetReg, build->GetConstantInt(v->ValueType->Size));
|
||||
emitval.Free(build);
|
||||
}
|
||||
}
|
||||
build->Registers[REGT_INT].Return(arrOffsetReg, 1);
|
||||
|
||||
return ExpEmit();
|
||||
}
|
||||
|
|
|
@ -301,6 +301,7 @@ enum EFxType
|
|||
EFX_ColorLiteral,
|
||||
EFX_GetDefaultByType,
|
||||
EFX_FontCast,
|
||||
EFX_LocalArrayDeclaration,
|
||||
EFX_COUNT
|
||||
};
|
||||
|
||||
|
@ -1806,6 +1807,7 @@ class FxCompoundStatement : public FxSequence
|
|||
friend class FxLocalVariableDeclaration;
|
||||
friend class FxStaticArray;
|
||||
friend class FxMultiAssign;
|
||||
friend class FxLocalArrayDeclaration;
|
||||
|
||||
public:
|
||||
FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {}
|
||||
|
@ -2123,6 +2125,7 @@ class FxLocalVariableDeclaration : public FxExpression
|
|||
friend class FxCompoundStatement;
|
||||
friend class FxLocalVariable;
|
||||
friend class FxStaticArrayVariable;
|
||||
friend class FxLocalArrayDeclaration;
|
||||
|
||||
FName Name;
|
||||
FxExpression *Init;
|
||||
|
@ -2181,4 +2184,22 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxLocalArrayDeclaration : public FxLocalVariableDeclaration
|
||||
{
|
||||
PType *ElementType;
|
||||
FArgumentList values;
|
||||
|
||||
public:
|
||||
|
||||
FxLocalArrayDeclaration(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3566,17 +3566,18 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
type = ztype;
|
||||
}
|
||||
|
||||
FxExpression *val;
|
||||
if (node->InitIsArray)
|
||||
{
|
||||
Error(node, "Compound initializer not implemented yet");
|
||||
val = nullptr;
|
||||
FArgumentList args;
|
||||
ConvertNodeList(args, node->Init);
|
||||
// This has to let the code generator resolve the constants, not the Simplifier, which lacks all the necessary type info.
|
||||
list->Add(new FxLocalArrayDeclaration(ztype, node->Name, args, *ast));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = node->Init ? ConvertNode(node->Init) : nullptr;
|
||||
FxExpression *val = node->Init ? ConvertNode(node->Init) : nullptr;
|
||||
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar.
|
||||
}
|
||||
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar.
|
||||
|
||||
node = static_cast<decltype(node)>(node->SiblingNext);
|
||||
} while (node != loc->Vars);
|
||||
|
|
Loading…
Reference in a new issue