Added support for implicitly-sized initialized arrays.

Also fixed dynamic arrays not being cleared before initializing.
This commit is contained in:
Chronos Ouroboros 2019-01-06 23:13:51 -02:00 committed by Christoph Oelckers
parent a1ae01e392
commit 4fdcc47edc
4 changed files with 62 additions and 8 deletions

View file

@ -11406,6 +11406,7 @@ FxLocalArrayDeclaration::FxLocalArrayDeclaration(PType *type, FName name, FArgum
{ {
ExprType = EFX_LocalArrayDeclaration; ExprType = EFX_LocalArrayDeclaration;
values = std::move(args); values = std::move(args);
clearExpr = nullptr;
} }
FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx) FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx)
@ -11421,6 +11422,16 @@ FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx)
auto elementType = (static_cast<PArray *> (ValueType))->ElementType; auto elementType = (static_cast<PArray *> (ValueType))->ElementType;
auto elementCount = (static_cast<PArray *> (ValueType))->ElementCount; auto elementCount = (static_cast<PArray *> (ValueType))->ElementCount;
// We HAVE to clear dynamic arrays before initializing them
if (IsDynamicArray())
{
FArgumentList argsList;
argsList.Clear();
clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, (const FScriptPosition) ScriptPosition);
SAFE_RESOLVE(clearExpr, ctx);
}
if (values.Size() > elementCount) if (values.Size() > elementCount)
{ {
ScriptPosition.Message(MSG_ERROR, "Initializer contains more elements than the array can contain"); ScriptPosition.Message(MSG_ERROR, "Initializer contains more elements than the array can contain");
@ -11477,6 +11488,11 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
{ {
assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters. assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters.
if (IsDynamicArray() && clearExpr != nullptr)
{
clearExpr->Emit(build);
}
auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize); auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize);
auto arrOffsetReg = build->Registers[REGT_INT].Get(1); auto arrOffsetReg = build->Registers[REGT_INT].Get(1);
build->Emit(OP_LK, arrOffsetReg, build->GetConstantInt(StackOffset)); build->Emit(OP_LK, arrOffsetReg, build->GetConstantInt(StackOffset));

View file

@ -2194,6 +2194,7 @@ class FxLocalArrayDeclaration : public FxLocalVariableDeclaration
{ {
PType *ElementType; PType *ElementType;
FArgumentList values; FArgumentList values;
FxExpression *clearExpr;
public: public:

View file

@ -1288,7 +1288,13 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
if (field->Type->ArraySize != nullptr) if (field->Type->ArraySize != nullptr)
{ {
fieldtype = ResolveArraySize(fieldtype, field->Type->ArraySize, type); bool nosize;
fieldtype = ResolveArraySize(fieldtype, field->Type->ArraySize, type, &nosize);
if (nosize)
{
Error(field, "Must specify array size");
}
} }
auto name = field->Names; auto name = field->Names;
@ -1304,7 +1310,13 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
auto thisfieldtype = fieldtype; auto thisfieldtype = fieldtype;
if (name->ArraySize != nullptr) if (name->ArraySize != nullptr)
{ {
thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, type); bool nosize;
thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, type, &nosize);
if (nosize)
{
Error(field, "Must specify array size");
}
} }
if (varflags & VARF_Native) if (varflags & VARF_Native)
@ -1805,7 +1817,7 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo
// //
//========================================================================== //==========================================================================
PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls) PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize)
{ {
TArray<ZCC_Expression *> indices; TArray<ZCC_Expression *> indices;
@ -1817,6 +1829,11 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
node = static_cast<ZCC_Expression*>(node->SiblingNext); node = static_cast<ZCC_Expression*>(node->SiblingNext);
} while (node != arraysize); } while (node != arraysize);
if (indices.Size() == 1 && indices [0]->Operation == PEX_Nil)
{
*nosize = true;
return baseType;
}
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false);
for (auto node : indices) for (auto node : indices)
@ -1839,6 +1856,8 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
} }
baseType = NewArray(baseType, size); baseType = NewArray(baseType, size);
} }
*nosize = false;
return baseType; return baseType;
} }
@ -3541,30 +3560,48 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
if (loc->Type->ArraySize != nullptr) if (loc->Type->ArraySize != nullptr)
{ {
ztype = ResolveArraySize(ztype, loc->Type->ArraySize, ConvertClass); bool nosize;
ztype = ResolveArraySize(ztype, loc->Type->ArraySize, ConvertClass, &nosize);
if (nosize)
{
Error(node, "Must specify array size");
}
} }
do do
{ {
PType *type; PType *type;
bool nosize = false;
if (node->ArraySize != nullptr) if (node->ArraySize != nullptr)
{ {
type = ResolveArraySize(ztype, node->ArraySize, ConvertClass); type = ResolveArraySize(ztype, node->ArraySize, ConvertClass, &nosize);
if (nosize && !node->InitIsArray)
{
Error(node, "Must specify array size for non-initialized arrays");
}
} }
else else
{ {
type = ztype; type = ztype;
} }
if (node->InitIsArray) if (node->InitIsArray && (type->isArray() || type->isDynArray() || nosize))
{ {
if (static_cast<PArray *>(type)->ElementType->isArray ()) auto arrtype = static_cast<PArray *>(type);
if (!nosize && (arrtype->ElementType->isArray() || arrtype->ElementType->isDynArray()))
{ {
Error(node, "Compound initializer not implemented yet for multi-dimensional arrays"); Error(node, "Compound initializer not implemented yet for multi-dimensional arrays");
} }
FArgumentList args; FArgumentList args;
ConvertNodeList(args, node->Init); ConvertNodeList(args, node->Init);
if (nosize)
{
type = NewArray(type, args.Size());
}
list->Add(new FxLocalArrayDeclaration(type, node->Name, args, 0, *node)); list->Add(new FxLocalArrayDeclaration(type, node->Name, args, 0, *node));
} }
else else

View file

@ -114,7 +114,7 @@ private:
bool CompileFlagDefs(PClass *type, TArray<ZCC_FlagDef *> &FlagDefs, FName prefix); bool CompileFlagDefs(PClass *type, TArray<ZCC_FlagDef *> &FlagDefs, FName prefix);
FString FlagsToString(uint32_t flags); FString FlagsToString(uint32_t flags);
PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember);
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize);
PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype);
void InitDefaults(); void InitDefaults();