- added property definitions to the ZScript parser. This will allow defining custom properties for the default block in custom base classes. See 'Health' for an example.
- support transient object member variables for information that does not need to be put in a savegame. - fixed: special initialization of objects needs to pass the proper defaults along, otherwise the parent classes will use their own, inappropriate one.
This commit is contained in:
parent
0c3aab794f
commit
179b6e1a39
21 changed files with 313 additions and 109 deletions
|
|
@ -120,6 +120,10 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
|
|||
}
|
||||
break;
|
||||
|
||||
case AST_Property:
|
||||
cls->Properties.Push(static_cast<ZCC_Property *>(node));
|
||||
break;
|
||||
|
||||
case AST_VarDeclarator:
|
||||
cls->Fields.Push(static_cast<ZCC_VarDeclarator *>(node));
|
||||
break;
|
||||
|
|
@ -396,6 +400,7 @@ int ZCCCompiler::Compile()
|
|||
CreateStructTypes();
|
||||
CompileAllConstants();
|
||||
CompileAllFields();
|
||||
CompileAllProperties();
|
||||
InitDefaults();
|
||||
InitFunctions();
|
||||
CompileStates();
|
||||
|
|
@ -1269,6 +1274,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
|||
if (field->Flags & ZCC_Protected) varflags |= VARF_Protected;
|
||||
if (field->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
|
||||
if (field->Flags & ZCC_ReadOnly) varflags |= VARF_ReadOnly;
|
||||
if (field->Flags & ZCC_Transient) varflags |= VARF_Transient;
|
||||
|
||||
if (field->Flags & ZCC_Native)
|
||||
{
|
||||
|
|
@ -1277,7 +1283,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
|||
|
||||
if (field->Flags & ZCC_Meta)
|
||||
{
|
||||
varflags |= VARF_Static|VARF_ReadOnly; // metadata implies readonly
|
||||
varflags |= VARF_Meta | VARF_Static | VARF_ReadOnly; // metadata implies readonly
|
||||
if (!(field->Flags & ZCC_Native))
|
||||
{
|
||||
// Non-native meta data is not implemented yet and requires some groundwork in the class copy code.
|
||||
|
|
@ -1303,7 +1309,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
|||
|
||||
if (varflags & VARF_Native)
|
||||
{
|
||||
auto querytype = (varflags & VARF_Static) ? type->GetClass() : type;
|
||||
auto querytype = (varflags & VARF_Meta) ? type->GetClass() : type;
|
||||
fd = FindField(querytype, FName(name->Name).GetChars());
|
||||
if (fd == nullptr)
|
||||
{
|
||||
|
|
@ -1337,6 +1343,68 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
|||
return Fields.Size() == 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: CompileAllProperties
|
||||
//
|
||||
// builds the property lists of all actor classes
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ZCCCompiler::CompileAllProperties()
|
||||
{
|
||||
for (auto c : Classes)
|
||||
{
|
||||
if (c->Properties.Size() > 0)
|
||||
CompileProperties(c->Type(), c->Properties, c->Type()->TypeName);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: CompileProperties
|
||||
//
|
||||
// builds the internal structure of a single class or struct
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool ZCCCompiler::CompileProperties(PClass *type, TArray<ZCC_Property *> &Properties, FName prefix)
|
||||
{
|
||||
if (!type->IsKindOf(RUNTIME_CLASS(PClassActor)))
|
||||
{
|
||||
Error(Properties[0], "Properties can only be defined for actors");
|
||||
return false;
|
||||
}
|
||||
for(auto p : Properties)
|
||||
{
|
||||
TArray<PField *> fields;
|
||||
ZCC_Identifier *id = (ZCC_Identifier *)p->Body;
|
||||
|
||||
do
|
||||
{
|
||||
auto f = dyn_cast<PField>(type->Symbols.FindSymbol(id->Id, true));
|
||||
if (f == nullptr)
|
||||
{
|
||||
Error(id, "Variable %s not found in %s", FName(id->Id).GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
fields.Push(f);
|
||||
id = (ZCC_Identifier*)id->SiblingNext;
|
||||
} while (id != p->Body);
|
||||
|
||||
FString qualifiedname;
|
||||
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
||||
// All these will be removed from the symbol table after the compiler finishes to free up the allocated space.
|
||||
if (prefix == NAME_None) qualifiedname.Format("@property@%s", FName(p->NodeName).GetChars());
|
||||
else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), FName(p->NodeName).GetChars());
|
||||
fields.ShrinkToFit();
|
||||
if (!type->Symbols.AddSymbol(new PProperty(qualifiedname, fields)))
|
||||
{
|
||||
Error(id, "Unable to add property %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: FieldFlagsToString
|
||||
|
|
@ -1841,6 +1909,73 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses an actor property's parameters and calls the handler
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *property, AActor *defaults, Baggage &bag)
|
||||
{
|
||||
unsigned parmcount = 1;
|
||||
ZCC_TreeNode *x = property->Values;
|
||||
while (x->SiblingNext != property->Values)
|
||||
{
|
||||
x = x->SiblingNext;
|
||||
parmcount++;
|
||||
}
|
||||
if (parmcount != prop->Variables.Size())
|
||||
{
|
||||
Error(x, "Argument count mismatch: Got %u, expected %u", parmcount, prop->Variables.Size());
|
||||
return;
|
||||
}
|
||||
|
||||
auto values = Simplify(property->Values, &bag.Info->Symbols, true); // need to do this before the loop so that we can find the head node again.
|
||||
auto exp = values;
|
||||
for (auto f : prop->Variables)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
if (f->Flags & VARF_Meta)
|
||||
{
|
||||
addr = ((char*)bag.Info) + f->Offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = ((char*)defaults) + f->Offset;
|
||||
}
|
||||
|
||||
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
static_cast<PInt*>(f->Type)->SetValue(addr, GetInt(exp));
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat)))
|
||||
{
|
||||
static_cast<PFloat*>(f->Type)->SetValue(addr, GetDouble(exp));
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
|
||||
{
|
||||
*(FString*)addr = GetString(exp);
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
auto cls = PClass::FindClass(GetString(exp));
|
||||
*(PClass**)addr = cls;
|
||||
if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
{
|
||||
Error(property, "class %s is not compatible with property type %s", cls->TypeName.GetChars(), static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(property, "unhandled property type %s", f->Type->DescriptiveName());
|
||||
}
|
||||
exp->ToErrorNode(); // invalidate after processing.
|
||||
exp = static_cast<ZCC_Expression *>(exp->SiblingNext);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses an actor property
|
||||
|
|
@ -1893,6 +2028,17 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro
|
|||
}
|
||||
else
|
||||
{
|
||||
propname.Insert(0, "@property@");
|
||||
FName name(propname, true);
|
||||
if (name != NAME_None)
|
||||
{
|
||||
auto propp = dyn_cast<PProperty>(cls->Symbols.FindSymbol(name, true));
|
||||
if (propp != nullptr)
|
||||
{
|
||||
DispatchScriptProperty(propp, prop, (AActor *)bag.Info->Defaults, bag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Error(prop, "'%s' is an unknown actor property\n", propname.GetChars());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue