Merge branch 'master' of https://github.com/coelckers/gzdoom into master

This commit is contained in:
alexey.lysiuk 2017-01-23 22:48:16 +02:00
commit 6586877ac5
20 changed files with 297 additions and 223 deletions

View file

@ -379,7 +379,7 @@ static void MarkRoot()
Mark(PClass::AllClasses[i]); Mark(PClass::AllClasses[i]);
} }
// Mark global symbols // Mark global symbols
GlobalSymbols.MarkSymbols(); Namespaces.MarkSymbols();
// Mark bot stuff. // Mark bot stuff.
Mark(bglobal.firstthing); Mark(bglobal.firstthing);
Mark(bglobal.body1); Mark(bglobal.body1);

View file

@ -65,8 +65,9 @@ EXTERN_CVAR(Bool, strictdecorate);
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
FNamespaceManager Namespaces;
FTypeTable TypeTable; FTypeTable TypeTable;
PSymbolTable GlobalSymbols;
TArray<PClass *> PClass::AllClasses; TArray<PClass *> PClass::AllClasses;
bool PClass::bShutdown; bool PClass::bShutdown;
bool PClass::bVMOperational; bool PClass::bVMOperational;
@ -117,7 +118,7 @@ void DumpTypeTable()
Printf("%4zu:", i); Printf("%4zu:", i);
for (PType *ty = TypeTable.TypeHash[i]; ty != NULL; ty = ty->HashNext) for (PType *ty = TypeTable.TypeHash[i]; ty != NULL; ty = ty->HashNext)
{ {
Printf(" -> %s", ty->IsKindOf(RUNTIME_CLASS(PNamedType)) ? static_cast<PNamedType*>(ty)->TypeName.GetChars(): ty->GetClass()->TypeName.GetChars()); Printf(" -> %s", ty->DescriptiveName());
len++; len++;
all++; all++;
} }
@ -434,7 +435,7 @@ void PType::StaticInit()
TypeVoidPtr = NewPointer(TypeVoid, false); TypeVoidPtr = NewPointer(TypeVoid, false);
TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value.
TypeStringStruct = NewNativeStruct(NAME_String, nullptr); TypeStringStruct = NewNativeStruct("Stringstruct", nullptr);
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
TypeColorStruct->AddField(NAME_a, TypeUInt8); TypeColorStruct->AddField(NAME_a, TypeUInt8);
TypeColorStruct->AddField(NAME_r, TypeUInt8); TypeColorStruct->AddField(NAME_r, TypeUInt8);
@ -472,24 +473,24 @@ void PType::StaticInit()
GlobalSymbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_uShort, TypeUInt16)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uShort, TypeUInt16));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Int, TypeSInt32)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Int, TypeSInt32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_uInt, TypeUInt32)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uInt, TypeUInt32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Bool, TypeBool)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Bool, TypeBool));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float, TypeFloat64)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Double, TypeFloat64)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Double, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float32, TypeFloat32)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float32, TypeFloat32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float64, TypeFloat64)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float64, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_String, TypeString)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_String, TypeString));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Name, TypeName)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Name, TypeName));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_State, TypeState)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_State, TypeState));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3)); Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3));
} }
@ -1692,7 +1693,7 @@ PClassPointer *NewClassPointer(PClass *restrict)
IMPLEMENT_CLASS(PEnum, false, true) IMPLEMENT_CLASS(PEnum, false, true)
IMPLEMENT_POINTERS_START(PEnum) IMPLEMENT_POINTERS_START(PEnum)
IMPLEMENT_POINTER(ValueType) IMPLEMENT_POINTER(Outer)
IMPLEMENT_POINTERS_END IMPLEMENT_POINTERS_END
//========================================================================== //==========================================================================
@ -1702,7 +1703,7 @@ IMPLEMENT_POINTERS_END
//========================================================================== //==========================================================================
PEnum::PEnum() PEnum::PEnum()
: ValueType(NULL) : PInt(4, false)
{ {
mDescriptiveName = "Enum"; mDescriptiveName = "Enum";
} }
@ -1714,8 +1715,10 @@ PEnum::PEnum()
//========================================================================== //==========================================================================
PEnum::PEnum(FName name, PTypeBase *outer) PEnum::PEnum(FName name, PTypeBase *outer)
: PNamedType(name, outer), ValueType(NULL) : PInt(4, false)
{ {
EnumName = name;
Outer = outer;
mDescriptiveName.Format("Enum<%s>", name.GetChars()); mDescriptiveName.Format("Enum<%s>", name.GetChars());
} }
@ -1731,6 +1734,7 @@ PEnum::PEnum(FName name, PTypeBase *outer)
PEnum *NewEnum(FName name, PTypeBase *outer) PEnum *NewEnum(FName name, PTypeBase *outer)
{ {
size_t bucket; size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket); PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket);
if (etype == NULL) if (etype == NULL)
{ {
@ -2373,6 +2377,7 @@ size_t PStruct::PropagateMark()
PStruct *NewStruct(FName name, PTypeBase *outer) PStruct *NewStruct(FName name, PTypeBase *outer)
{ {
size_t bucket; size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket); PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket);
if (stype == NULL) if (stype == NULL)
{ {
@ -2392,8 +2397,8 @@ IMPLEMENT_CLASS(PNativeStruct, false, false)
// //
//========================================================================== //==========================================================================
PNativeStruct::PNativeStruct(FName name) PNativeStruct::PNativeStruct(FName name, PTypeBase *outer)
: PStruct(name, nullptr) : PStruct(name, outer)
{ {
mDescriptiveName.Format("NativeStruct<%s>", name.GetChars()); mDescriptiveName.Format("NativeStruct<%s>", name.GetChars());
Size = 0; Size = 0;
@ -2411,10 +2416,11 @@ PNativeStruct::PNativeStruct(FName name)
PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer) PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer)
{ {
size_t bucket; size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket); PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket);
if (stype == NULL) if (stype == NULL)
{ {
stype = new PNativeStruct(name); stype = new PNativeStruct(name, outer);
TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket); TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket);
} }
return static_cast<PNativeStruct *>(stype); return static_cast<PNativeStruct *>(stype);
@ -2796,6 +2802,7 @@ void PClass::StaticInit ()
atterm (StaticShutdown); atterm (StaticShutdown);
StaticBootstrap(); StaticBootstrap();
Namespaces.GlobalNamespace = Namespaces.NewNamespace(0);
FAutoSegIterator probe(CRegHead, CRegTail); FAutoSegIterator probe(CRegHead, CRegTail);
@ -2843,7 +2850,7 @@ void PClass::StaticShutdown ()
// Unless something went wrong, anything left here should be class and type objects only, which do not own any scripts. // Unless something went wrong, anything left here should be class and type objects only, which do not own any scripts.
TypeTable.Clear(); TypeTable.Clear();
GlobalSymbols.ReleaseSymbols(); Namespaces.ReleaseSymbols();
for (i = 0; i < PClass::AllClasses.Size(); ++i) for (i = 0; i < PClass::AllClasses.Size(); ++i)
{ {
@ -3039,14 +3046,14 @@ void PClass::InsertIntoHash ()
size_t bucket; size_t bucket;
PType *found; PType *found;
found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket); found = TypeTable.FindType(RUNTIME_CLASS(PClass), 0, TypeName, &bucket);
if (found != NULL) if (found != NULL)
{ // This type has already been inserted { // This type has already been inserted
I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
} }
else else
{ {
TypeTable.AddType(this, RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, bucket); TypeTable.AddType(this, RUNTIME_CLASS(PClass), 0, TypeName, bucket);
} }
} }
@ -3084,8 +3091,7 @@ PClass *PClass::FindClass (FName zaname)
{ {
return NULL; return NULL;
} }
return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), 0, zaname, NULL));
/*FIXME:Outer*/0, zaname, NULL));
} }
//========================================================================== //==========================================================================
@ -3376,7 +3382,7 @@ PClass *PClass::FindClassTentative(FName name)
Derive(type, name); Derive(type, name);
type->Size = TentativeClass; type->Size = TentativeClass;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket);
return type; return type;
} }
@ -3835,3 +3841,60 @@ PSymbol *PSymbolTable::ReplaceSymbol(PSymbol *newsym)
Symbols.Insert(newsym->SymbolName, newsym); Symbols.Insert(newsym->SymbolName, newsym);
return NULL; return NULL;
} }
IMPLEMENT_CLASS(PNamespace, false, true)
IMPLEMENT_POINTERS_START(PNamespace)
IMPLEMENT_POINTER(Parent)
IMPLEMENT_POINTERS_END
PNamespace::PNamespace(int filenum, PNamespace *parent)
{
Parent = parent;
if (parent) Symbols.SetParentTable(&parent->Symbols);
FileNum = filenum;
}
size_t PNamespace::PropagateMark()
{
GC::Mark(Parent);
return Symbols.MarkSymbols() + 1;
}
FNamespaceManager::FNamespaceManager()
{
GlobalNamespace = nullptr;
}
PNamespace *FNamespaceManager::NewNamespace(int filenum)
{
PNamespace *parent = nullptr;
// The parent will be the last namespace with this or a lower filenum.
// This ensures that DECORATE won't see the symbols of later files.
for (int i = AllNamespaces.Size() - 1; i >= 0; i--)
{
if (AllNamespaces[i]->FileNum <= filenum)
{
parent = AllNamespaces[i];
break;
}
}
auto newns = new PNamespace(filenum, parent);
AllNamespaces.Push(newns);
return newns;
}
size_t FNamespaceManager::MarkSymbols()
{
for (auto ns : AllNamespaces)
{
GC::Mark(ns);
}
return AllNamespaces.Size();
}
void FNamespaceManager::ReleaseSymbols()
{
GlobalNamespace = nullptr;
AllNamespaces.Clear();
}

View file

@ -171,8 +171,6 @@ public:
PSymbolTreeNode() : PSymbol(NAME_None) {} PSymbolTreeNode() : PSymbol(NAME_None) {}
}; };
extern PSymbolTable GlobalSymbols;
// Basic information shared by all types ------------------------------------ // Basic information shared by all types ------------------------------------
// Only one copy of a type is ever instantiated at one time. // Only one copy of a type is ever instantiated at one time.
@ -593,15 +591,15 @@ protected:
// Compound types ----------------------------------------------------------- // Compound types -----------------------------------------------------------
class PEnum : public PNamedType class PEnum : public PInt
{ {
DECLARE_CLASS(PEnum, PNamedType); DECLARE_CLASS(PEnum, PInt);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
public: public:
PEnum(FName name, PTypeBase *outer); PEnum(FName name, PTypeBase *outer);
PType *ValueType; PTypeBase *Outer;
TMap<FName, int> Values; FName EnumName;
protected: protected:
PEnum(); PEnum();
}; };
@ -710,7 +708,7 @@ class PNativeStruct : public PStruct
{ {
DECLARE_CLASS(PNativeStruct, PStruct); DECLARE_CLASS(PNativeStruct, PStruct);
public: public:
PNativeStruct(FName name = NAME_None); PNativeStruct(FName name = NAME_None, PTypeBase *outer = nullptr);
}; };
class PPrototype : public PCompoundType class PPrototype : public PCompoundType
@ -986,31 +984,39 @@ public:
PSymbolConstString() {} PSymbolConstString() {}
}; };
// Enumerations for serializing types in an archive ------------------------- // Namespaces --------------------------------------------------
enum ETypeVal : BYTE class PNamespace : public PTypeBase
{ {
VAL_Int8, DECLARE_CLASS(PNamespace, PTypeBase)
VAL_UInt8, HAS_OBJECT_POINTERS;
VAL_Int16,
VAL_UInt16, public:
VAL_Int32, PSymbolTable Symbols;
VAL_UInt32, PNamespace *Parent;
VAL_Int64, int FileNum; // This is for blocking DECORATE access to later files.
VAL_UInt64,
VAL_Zero, PNamespace() {}
VAL_One, PNamespace(int filenum, PNamespace *parent);
VAL_Float32, size_t PropagateMark();
VAL_Float64,
VAL_String,
VAL_Name,
VAL_Struct,
VAL_Array,
VAL_Object,
VAL_State,
VAL_Class,
}; };
struct FNamespaceManager
{
PNamespace *GlobalNamespace;
TArray<PNamespace *> AllNamespaces;
FNamespaceManager();
PNamespace *NewNamespace(int filenum);
size_t MarkSymbols();
void ReleaseSymbols();
};
extern FNamespaceManager Namespaces;
// Enumerations for serializing types in an archive -------------------------
inline bool &DObject::BoolVar(FName field) inline bool &DObject::BoolVar(FName field)
{ {
return *(bool*)ScriptVar(field, TypeBool); return *(bool*)ScriptVar(field, TypeBool);

View file

@ -95,14 +95,14 @@ static const FLOP FxFlops[] =
// //
//========================================================================== //==========================================================================
FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump) FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump)
: ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(lump) : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(lump), CurGlobals(cg)
{ {
if (fnc != nullptr) Class = fnc->OwningClass; if (fnc != nullptr) Class = fnc->OwningClass;
} }
FCompileContext::FCompileContext(PStruct *cls, bool fromdecorate) FCompileContext::FCompileContext(PNamespace *cg, PStruct *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg)
{ {
} }
@ -119,7 +119,7 @@ PSymbol *FCompileContext::FindInSelfClass(FName identifier, PSymbolTable *&symt)
} }
PSymbol *FCompileContext::FindGlobal(FName identifier) PSymbol *FCompileContext::FindGlobal(FName identifier)
{ {
return GlobalSymbols.FindSymbol(identifier, true); return CurGlobals->Symbols.FindSymbol(identifier, true);
} }
void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
@ -185,16 +185,30 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
} }
} }
static PStruct *FindStructType(FName name) static PStruct *FindStructType(FName name, FCompileContext &ctx)
{ {
PStruct *ccls = PClass::FindClass(name); auto sym = ctx.Class->Symbols.FindSymbol(name, true);
if (ccls == nullptr) if (sym == nullptr) sym = ctx.CurGlobals->Symbols.FindSymbol(name, true);
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{ {
ccls = dyn_cast<PStruct>(TypeTable.FindType(RUNTIME_CLASS(PStruct), 0, (intptr_t)name, nullptr)); auto type = static_cast<PSymbolType*>(sym);
if (ccls == nullptr) ccls = dyn_cast<PStruct>(TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), 0, (intptr_t)name, nullptr)); return dyn_cast<PStruct>(type->Type);
} }
return ccls; return nullptr;
} }
// This is for resolving class identifiers which need to be context aware, unlike class names.
static PClass *FindClassType(FName name, FCompileContext &ctx)
{
auto sym = ctx.CurGlobals->Symbols.FindSymbol(name, true);
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PClass>(type->Type);
}
return nullptr;
}
//========================================================================== //==========================================================================
// //
// ExpEmit // ExpEmit
@ -235,7 +249,7 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func) static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
{ {
PSymbol *sym = GlobalSymbols.FindSymbol(funcname, false); PSymbol *sym = Namespaces.GlobalNamespace->Symbols.FindSymbol(funcname, false);
if (sym == nullptr) if (sym == nullptr)
{ {
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
@ -243,7 +257,7 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall
calldec->PrintableName = funcname.GetChars(); calldec->PrintableName = funcname.GetChars();
symfunc->Function = calldec; symfunc->Function = calldec;
sym = symfunc; sym = symfunc;
GlobalSymbols.AddSymbol(sym); Namespaces.GlobalNamespace->Symbols.AddSymbol(sym);
} }
return sym; return sym;
} }
@ -5918,7 +5932,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{ {
// If the left side is a class name for a static member function call it needs to be resolved manually // If the left side is a class name for a static member function call it needs to be resolved manually
// because the resulting value type would cause problems in nearly every other place where identifiers are being used. // because the resulting value type would cause problems in nearly every other place where identifiers are being used.
ccls = FindStructType(static_cast<FxIdentifier *>(Object)->Identifier); ccls = FindStructType(static_cast<FxIdentifier *>(Object)->Identifier, ctx);
if (ccls != nullptr) static_cast<FxIdentifier *>(Object)->noglobal = true; if (ccls != nullptr) static_cast<FxIdentifier *>(Object)->noglobal = true;
} }
@ -7256,7 +7270,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(ctx); return x->Resolve(ctx);
} }
PClass *cls = PClass::FindClass(MethodName); PClass *cls = FindClassType(MethodName, ctx);
if (cls != nullptr && cls->bExported) if (cls != nullptr && cls->bExported)
{ {
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
@ -7487,9 +7501,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (Self->ExprType == EFX_Identifier) if (Self->ExprType == EFX_Identifier)
{ {
auto id = static_cast<FxIdentifier *>(Self)->Identifier;
// If the left side is a class name for a static member function call it needs to be resolved manually // If the left side is a class name for a static member function call it needs to be resolved manually
// because the resulting value type would cause problems in nearly every other place where identifiers are being used. // because the resulting value type would cause problems in nearly every other place where identifiers are being used.
ccls = FindStructType(static_cast<FxIdentifier *>(Self)->Identifier); if (id == NAME_String) ccls = TypeStringStruct;
else ccls = FindStructType(id, ctx);
if (ccls != nullptr) static_cast<FxIdentifier *>(Self)->noglobal = true; if (ccls != nullptr) static_cast<FxIdentifier *>(Self)->noglobal = true;
} }
@ -7500,8 +7516,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (ccls != nullptr) if (ccls != nullptr)
{ {
// [ZZ] substitute ccls for String internal type. // [ZZ] substitute ccls for String internal type.
if (ccls->TypeName == NAME_String)
ccls = TypeStringStruct;
if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast<PClass *>(ccls)->bExported) if (!ccls->IsKindOf(RUNTIME_CLASS(PClass)) || static_cast<PClass *>(ccls)->bExported)
{ {
cls = ccls; cls = ccls;
@ -9977,7 +9991,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
if (clsname != NAME_None) if (clsname != NAME_None)
{ {
cls = PClass::FindClass(clsname); cls = FindClassType(clsname, ctx);
if (cls == nullptr) if (cls == nullptr)
{ {
/* lax */ /* lax */

View file

@ -84,9 +84,10 @@ struct FCompileContext
int Lump; int Lump;
bool Unsafe = false; bool Unsafe = false;
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs; TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
PNamespace *CurGlobals;
FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump); FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump);
FCompileContext(PStruct *cls, bool fromdecorate); // only to be used to resolve constants! FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);

View file

@ -100,7 +100,7 @@ static const char *RenderStyles[] =
//========================================================================== //==========================================================================
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName); PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName);
void ParseOldDecoration(FScanner &sc, EDefinitionType def) void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
{ {
Baggage bag; Baggage bag;
TArray<FState> StateArray; TArray<FState> StateArray;
@ -116,6 +116,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
typeName = FName(sc.String); typeName = FName(sc.String);
type = DecoDerivedClass(FScriptPosition(sc), parent, typeName); type = DecoDerivedClass(FScriptPosition(sc), parent, typeName);
ResetBaggage(&bag, parent); ResetBaggage(&bag, parent);
bag.Namespace = ns;
bag.Info = type; bag.Info = type;
bag.fromDecorate = true; bag.fromDecorate = true;
#ifdef _DEBUG #ifdef _DEBUG

View file

@ -82,13 +82,13 @@ static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls);
static FxExpression *ParseExpressionA (FScanner &sc, PClassActor *cls); static FxExpression *ParseExpressionA (FScanner &sc, PClassActor *cls);
static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls); static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls);
FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve) FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, PNamespace *spc)
{ {
FxExpression *data = ParseExpressionM (sc, cls); FxExpression *data = ParseExpressionM (sc, cls);
if (mustresolve) if (spc)
{ {
FCompileContext ctx(cls, true); FCompileContext ctx(spc, cls, true);
data = data->Resolve(ctx); data = data->Resolve(ctx);
} }

View file

@ -56,7 +56,7 @@
#include "v_text.h" #include "v_text.h"
#include "m_argv.h" #include "m_argv.h"
void ParseOldDecoration(FScanner &sc, EDefinitionType def); void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns);
EXTERN_CVAR(Bool, strictdecorate); EXTERN_CVAR(Bool, strictdecorate);
@ -101,12 +101,11 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN
// //
// ParseParameter // ParseParameter
// //
// Parses a parameter - either a default in a function declaration // Parses an argument in a function call.
// or an argument in a function call.
// //
//========================================================================== //==========================================================================
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant) FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type)
{ {
FxExpression *x = NULL; FxExpression *x = NULL;
int v; int v;
@ -118,12 +117,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
} }
else if (type == TypeBool || type == TypeSInt32 || type == TypeFloat64) else if (type == TypeBool || type == TypeSInt32 || type == TypeFloat64)
{ {
x = ParseExpression (sc, cls, constant); x = ParseExpression (sc, cls, nullptr);
if (constant && !x->isConstant())
{
sc.ScriptMessage("Default parameter must be constant.");
FScriptPosition::ErrorCounter++;
}
// Do automatic coercion between bools, ints and floats. // Do automatic coercion between bools, ints and floats.
if (type == TypeBool) if (type == TypeBool)
{ {
@ -193,11 +187,10 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
x = new FxMultiNameState(sc.String, sc); x = new FxMultiNameState(sc.String, sc);
} }
} }
else if (!constant) else
{ {
x = new FxRuntimeStateIndex(ParseExpression(sc, cls)); x = new FxRuntimeStateIndex(ParseExpression(sc, cls));
} }
else sc.MustGetToken(TK_StringConst); // This is for the error.
} }
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer)) else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
{ // Actor name { // Actor name
@ -222,7 +215,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
// //
//========================================================================== //==========================================================================
static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls) static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls, PNamespace *ns)
{ {
// Read the type and make sure it's int or float. // Read the type and make sure it's int or float.
if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Float)) if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Float))
@ -231,7 +224,7 @@ static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
sc.MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
FName symname = sc.String; FName symname = sc.String;
sc.MustGetToken('='); sc.MustGetToken('=');
FxExpression *expr = ParseExpression (sc, cls, true); FxExpression *expr = ParseExpression (sc, cls, ns);
sc.MustGetToken(';'); sc.MustGetToken(';');
if (expr == nullptr) if (expr == nullptr)
@ -283,7 +276,7 @@ static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
// //
//========================================================================== //==========================================================================
static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls) static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls, PNamespace *ns)
{ {
int currvalue = 0; int currvalue = 0;
@ -294,7 +287,7 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
FName symname = sc.String; FName symname = sc.String;
if (sc.CheckToken('=')) if (sc.CheckToken('='))
{ {
FxExpression *expr = ParseExpression (sc, cls, true); FxExpression *expr = ParseExpression (sc, cls, ns);
if (expr != nullptr) if (expr != nullptr)
{ {
if (!expr->isConstant()) if (!expr->isConstant())
@ -339,7 +332,7 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
// //
//========================================================================== //==========================================================================
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls) static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls, PNamespace *ns)
{ {
PType *type; PType *type;
int maxelems = 1; int maxelems = 1;
@ -381,7 +374,7 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
if (sc.CheckToken('[')) if (sc.CheckToken('['))
{ {
FxExpression *expr = ParseExpression(sc, cls, true); FxExpression *expr = ParseExpression(sc, cls, ns);
if (expr == nullptr) if (expr == nullptr)
{ {
sc.ScriptMessage("Error while resolving array size"); sc.ScriptMessage("Error while resolving array size");
@ -1112,11 +1105,12 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag)
// Reads an actor definition // Reads an actor definition
// //
//========================================================================== //==========================================================================
static void ParseActor(FScanner &sc) static void ParseActor(FScanner &sc, PNamespace *ns)
{ {
PClassActor *info = NULL; PClassActor *info = NULL;
Baggage bag; Baggage bag;
bag.Namespace = ns;
bag.fromDecorate = true; bag.fromDecorate = true;
info = ParseActorHeader(sc, &bag); info = ParseActorHeader(sc, &bag);
sc.MustGetToken('{'); sc.MustGetToken('{');
@ -1125,15 +1119,15 @@ static void ParseActor(FScanner &sc)
switch (sc.TokenType) switch (sc.TokenType)
{ {
case TK_Const: case TK_Const:
ParseConstant (sc, &info->Symbols, info); ParseConstant (sc, &info->Symbols, info, ns);
break; break;
case TK_Enum: case TK_Enum:
ParseEnum (sc, &info->Symbols, info); ParseEnum (sc, &info->Symbols, info, ns);
break; break;
case TK_Var: case TK_Var:
ParseUserVariable (sc, &info->Symbols, info); ParseUserVariable (sc, &info->Symbols, info, ns);
break; break;
case TK_Identifier: case TK_Identifier:
@ -1225,6 +1219,7 @@ static void ParseDamageDefinition(FScanner &sc)
void ParseDecorate (FScanner &sc) void ParseDecorate (FScanner &sc)
{ {
auto ns = Namespaces.NewNamespace(sc.LumpNum);
// Get actor class name. // Get actor class name.
for(;;) for(;;)
{ {
@ -1255,11 +1250,11 @@ void ParseDecorate (FScanner &sc)
} }
case TK_Const: case TK_Const:
ParseConstant (sc, &GlobalSymbols, NULL); ParseConstant (sc, &ns->Symbols, NULL, ns);
break; break;
case TK_Enum: case TK_Enum:
ParseEnum (sc, &GlobalSymbols, NULL); ParseEnum (sc, &ns->Symbols, NULL, ns);
break; break;
case ';': case ';':
@ -1275,22 +1270,22 @@ void ParseDecorate (FScanner &sc)
// so let's do a special case for this. // so let's do a special case for this.
if (sc.Compare("ACTOR")) if (sc.Compare("ACTOR"))
{ {
ParseActor (sc); ParseActor (sc, ns);
break; break;
} }
else if (sc.Compare("PICKUP")) else if (sc.Compare("PICKUP"))
{ {
ParseOldDecoration (sc, DEF_Pickup); ParseOldDecoration (sc, DEF_Pickup, ns);
break; break;
} }
else if (sc.Compare("BREAKABLE")) else if (sc.Compare("BREAKABLE"))
{ {
ParseOldDecoration (sc, DEF_BreakableDecoration); ParseOldDecoration (sc, DEF_BreakableDecoration, ns);
break; break;
} }
else if (sc.Compare("PROJECTILE")) else if (sc.Compare("PROJECTILE"))
{ {
ParseOldDecoration (sc, DEF_Projectile); ParseOldDecoration (sc, DEF_Projectile, ns);
break; break;
} }
else if (sc.Compare("DAMAGETYPE")) else if (sc.Compare("DAMAGETYPE"))
@ -1300,7 +1295,7 @@ void ParseDecorate (FScanner &sc)
} }
default: default:
sc.RestorePos(pos); sc.RestorePos(pos);
ParseOldDecoration(sc, DEF_Decoration); ParseOldDecoration(sc, DEF_Decoration, ns);
break; break;
} }
} }

View file

@ -343,7 +343,7 @@ endofstate:
if (ScriptCode != nullptr) if (ScriptCode != nullptr)
{ {
auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags); auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags);
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum); state.ActionFunc = FunctionBuildList.AddFunction(bag.Namespace, funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum);
} }
int count = bag.statedef.AddStates(&state, statestring, scp); int count = bag.statedef.AddStates(&state, statestring, scp);
if (count < 0) if (count < 0)
@ -671,7 +671,7 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression
else else
{ {
// Use the generic parameter parser for everything else // Use the generic parameter parser for everything else
x = ParseParameter(sc, cls, params[pnum], false); x = ParseParameter(sc, cls, params[pnum]);
} }
out_params.Push(x); out_params.Push(x);
pnum++; pnum++;

View file

@ -216,7 +216,7 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
// //
//========================================================================== //==========================================================================
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum) void CreateDamageFunction(PNamespace *OutNamespace, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum)
{ {
if (id == nullptr) if (id == nullptr)
{ {
@ -226,7 +226,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
{ {
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0); auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0);
defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum); defaults->DamageFunc = FunctionBuildList.AddFunction(OutNamespace, funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum);
} }
} }

View file

@ -117,6 +117,7 @@ struct Baggage
#ifdef _DEBUG #ifdef _DEBUG
FString ClassName; // This is here so that during debugging the class name can be seen FString ClassName; // This is here so that during debugging the class name can be seen
#endif #endif
PNamespace *Namespace;
PClassActor *Info; PClassActor *Info;
bool DropItemSet; bool DropItemSet;
bool StateSet; bool StateSet;
@ -132,7 +133,7 @@ struct Baggage
inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
{ {
bag->DropItemList = NULL; bag->DropItemList = nullptr;
bag->DropItemSet = false; bag->DropItemSet = false;
bag->CurrentState = 0; bag->CurrentState = 0;
bag->fromDecorate = true; bag->fromDecorate = true;
@ -150,7 +151,7 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string);
FieldDesc *FindField(PStruct *cls, const char * string); FieldDesc *FindField(PStruct *cls, const char * string);
FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, bool mustresolve = false); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, PNamespace *resolvenspc = nullptr);
void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag); void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag);
void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression *> &out_params, void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression *> &out_params,
PFunction *afd, FString statestring, FStateDefinitions *statedef); PFunction *afd, FString statestring, FStateDefinitions *statedef);
@ -160,7 +161,7 @@ FName CheckCastKludges(FName in);
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PStruct *cls, DWORD funcflags, int useflags); void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PStruct *cls, DWORD funcflags, int useflags);
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error); PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error);
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum); void CreateDamageFunction(PNamespace *ns, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
//========================================================================== //==========================================================================
// //
@ -169,7 +170,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
//========================================================================== //==========================================================================
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod); void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant); FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type);
enum enum

View file

@ -762,16 +762,16 @@ void InitThingdef()
// expose the global validcount variable. // expose the global validcount variable.
PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount); PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount);
GlobalSymbols.AddSymbol(vcf); Namespaces.GlobalNamespace->Symbols.AddSymbol(vcf);
// expose the global Multiplayer variable. // expose the global Multiplayer variable.
PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer); PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer);
GlobalSymbols.AddSymbol(multif); Namespaces.GlobalNamespace->Symbols.AddSymbol(multif);
// set up a variable for the global level data structure // set up a variable for the global level data structure
PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr); PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr);
PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level);
GlobalSymbols.AddSymbol(levelf); Namespaces.GlobalNamespace->Symbols.AddSymbol(levelf);
// Add the game data arrays to LevelLocals. // Add the game data arrays to LevelLocals.
lstruct->AddNativeField("sectors", NewPointer(NewResizableArray(sectorstruct), false), myoffsetof(FLevelLocals, sectors), VARF_Native); lstruct->AddNativeField("sectors", NewPointer(NewResizableArray(sectorstruct), false), myoffsetof(FLevelLocals, sectors), VARF_Native);
@ -783,17 +783,17 @@ void InitThingdef()
auto aact = NewPointer(NewResizableArray(NewClassPointer(RUNTIME_CLASS(AActor))), true); auto aact = NewPointer(NewResizableArray(NewClassPointer(RUNTIME_CLASS(AActor))), true);
PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses); PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses);
GlobalSymbols.AddSymbol(aacf); Namespaces.GlobalNamespace->Symbols.AddSymbol(aacf);
// set up a variable for the DEH data // set up a variable for the DEH data
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
GlobalSymbols.AddSymbol(dehf); Namespaces.GlobalNamespace->Symbols.AddSymbol(dehf);
// set up a variable for the global gameinfo data // set up a variable for the global gameinfo data
PStruct *gistruct = NewNativeStruct("GameInfoStruct", nullptr); PStruct *gistruct = NewNativeStruct("GameInfoStruct", nullptr);
PField *gi = new PField("gameinfo", gistruct, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gameinfo); PField *gi = new PField("gameinfo", gistruct, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gameinfo);
GlobalSymbols.AddSymbol(gi); Namespaces.GlobalNamespace->Symbols.AddSymbol(gi);
// set up a variable for the global players array. // set up a variable for the global players array.
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
@ -801,33 +801,33 @@ void InitThingdef()
pstruct->Align = alignof(player_t); pstruct->Align = alignof(player_t);
PArray *parray = NewArray(pstruct, MAXPLAYERS); PArray *parray = NewArray(pstruct, MAXPLAYERS);
PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
pstruct->AddNativeField("weapons", NewNativeStruct("WeaponSlots", nullptr), myoffsetof(player_t, weapons), VARF_Native); pstruct->AddNativeField("weapons", NewNativeStruct("WeaponSlots", nullptr), myoffsetof(player_t, weapons), VARF_Native);
parray = NewArray(TypeBool, MAXPLAYERS); parray = NewArray(TypeBool, MAXPLAYERS);
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
playerf = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum); playerf = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
playerf = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze); playerf = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!! // is to create a static variable from it and reference that in the script. Yuck!!!
static AWeapon *wpnochg = WP_NOCHANGE; static AWeapon *wpnochg = WP_NOCHANGE;
playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg); playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
GlobalSymbols.AddSymbol(playerf); Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for (auto &fl : FlagLists) for (auto &fl : FlagLists)
@ -936,7 +936,7 @@ DEFINE_ACTION_FUNCTION(FStringTable, Localize)
ACTION_RETURN_STRING(GStrings(&label[1])); ACTION_RETURN_STRING(GStrings(&label[1]));
} }
DEFINE_ACTION_FUNCTION(FString, Replace) DEFINE_ACTION_FUNCTION(FStringStruct, Replace)
{ {
PARAM_SELF_STRUCT_PROLOGUE(FString); PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_STRING(s1); PARAM_STRING(s1);
@ -1103,14 +1103,14 @@ static FString FStringFormat(VM_ARGS)
return output; return output;
} }
DEFINE_ACTION_FUNCTION(FString, Format) DEFINE_ACTION_FUNCTION(FStringStruct, Format)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
FString s = FStringFormat(param, defaultparam, numparam, ret, numret); FString s = FStringFormat(param, defaultparam, numparam, ret, numret);
ACTION_RETURN_STRING(s); ACTION_RETURN_STRING(s);
} }
DEFINE_ACTION_FUNCTION(FString, AppendFormat) DEFINE_ACTION_FUNCTION(FStringStruct, AppendFormat)
{ {
PARAM_SELF_STRUCT_PROLOGUE(FString); PARAM_SELF_STRUCT_PROLOGUE(FString);
// first parameter is the self pointer // first parameter is the self pointer

View file

@ -689,7 +689,7 @@ DEFINE_PROPERTY(damage, X, Actor)
defaults->DamageVal = dmgval; defaults->DamageVal = dmgval;
// Only DECORATE can get here with a valid expression. // Only DECORATE can get here with a valid expression.
CreateDamageFunction(bag.Info, defaults, id, true, bag.Lumpnum); CreateDamageFunction(bag.Namespace, bag.Info, defaults, id, true, bag.Lumpnum);
} }
//========================================================================== //==========================================================================

View file

@ -802,7 +802,7 @@ void VMFunctionBuilder::BackpatchListToHere(TArray<size_t> &locs)
//========================================================================== //==========================================================================
FFunctionBuildList FunctionBuildList; FFunctionBuildList FunctionBuildList;
VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum) VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum)
{ {
auto func = code->GetDirectFunction(); auto func = code->GetDirectFunction();
if (func != nullptr) if (func != nullptr)
@ -814,6 +814,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
//Printf("Adding %s\n", name.GetChars()); //Printf("Adding %s\n", name.GetChars());
Item it; Item it;
assert(gnspc != nullptr);
it.CurGlobals = gnspc;
it.Func = functype; it.Func = functype;
it.Code = code; it.Code = code;
it.PrintableName = name; it.PrintableName = name;
@ -853,7 +855,7 @@ void FFunctionBuildList::Build()
assert(item.Code != NULL); assert(item.Code != NULL);
// We don't know the return type in advance for anonymous functions. // We don't know the return type in advance for anonymous functions.
FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount, item.Lump); FCompileContext ctx(item.CurGlobals, item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount, item.Lump);
// Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it.
VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); VMFunctionBuilder buildit(item.Func->GetImplicitArgs());

View file

@ -141,6 +141,7 @@ class FFunctionBuildList
FxExpression *Code = nullptr; FxExpression *Code = nullptr;
PPrototype *Proto = nullptr; PPrototype *Proto = nullptr;
VMScriptFunction *Function = nullptr; VMScriptFunction *Function = nullptr;
PNamespace *CurGlobals = nullptr;
FString PrintableName; FString PrintableName;
int StateIndex; int StateIndex;
int StateCount; int StateCount;
@ -151,7 +152,7 @@ class FFunctionBuildList
TArray<Item> mItems; TArray<Item> mItems;
public: public:
VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum); VMFunction *AddFunction(PNamespace *curglobals, PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum);
void Build(); void Build();
}; };

View file

@ -74,7 +74,7 @@ static FString GetStringConst(FxExpression *ex, FCompileContext &ctx)
int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls) int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls)
{ {
FCompileContext ctx(cls, false); FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxIntCast(ConvertNode(node), false); FxExpression *ex = new FxIntCast(ConvertNode(node), false);
ex = ex->Resolve(ctx); ex = ex->Resolve(ctx);
if (ex == nullptr) return 0; if (ex == nullptr) return 0;
@ -88,7 +88,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls)
FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls) FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls)
{ {
FCompileContext ctx(cls, false); FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxStringCast(ConvertNode(node)); FxExpression *ex = new FxStringCast(ConvertNode(node));
ex = ex->Resolve(ctx); ex = ex->Resolve(ctx);
if (ex == nullptr) return ""; if (ex == nullptr) return "";
@ -155,6 +155,11 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
break; break;
case AST_Struct: case AST_Struct:
if (static_cast<ZCC_Struct *>(node)->Flags & VARF_Native)
{
Error(node, "Cannot define native structs inside classes");
static_cast<ZCC_Struct *>(node)->Flags &= ~VARF_Native;
}
ProcessStruct(static_cast<ZCC_Struct *>(node), childnode, cls->cls); ProcessStruct(static_cast<ZCC_Struct *>(node), childnode, cls->cls);
break; break;
@ -271,8 +276,8 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
// //
//========================================================================== //==========================================================================
ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols, int lumpnum) ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PNamespace *_outnamespc, int lumpnum)
: Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), Lump(lumpnum) : Outer(_outer), GlobalTreeNodes(&_symbols), OutNamespace(_outnamespc), AST(ast), Lump(lumpnum)
{ {
FScriptPosition::ResetErrorCounter(); FScriptPosition::ResetErrorCounter();
// Group top-level nodes by type // Group top-level nodes by type
@ -303,8 +308,8 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
{ {
case AST_Enum: case AST_Enum:
zenumType = static_cast<ZCC_Enum *>(node); zenumType = static_cast<ZCC_Enum *>(node);
enumType = NewEnum(zenumType->NodeName, nullptr); enumType = NewEnum(zenumType->NodeName, OutNamespace);
GlobalSymbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType)); OutNamespace->Symbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType));
break; break;
case AST_Class: case AST_Class:
@ -468,13 +473,31 @@ void ZCCCompiler::CreateStructTypes()
{ {
for(auto s : Structs) for(auto s : Structs)
{ {
PTypeBase *outer;
PSymbolTable *syms;
s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType(); s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType();
if (s->strct->Flags & ZCC_Native) if (s->Outer)
s->strct->Type = NewNativeStruct(s->NodeName(), nullptr); {
outer = s->Outer;
syms = &s->Outer->Symbols;
}
else else
s->strct->Type = NewStruct(s->NodeName(), s->Outer); {
outer = OutNamespace;
syms = &OutNamespace->Symbols;
}
if (s->strct->Flags & ZCC_Native)
{
s->strct->Type = NewNativeStruct(s->NodeName(), outer);
}
else
{
s->strct->Type = NewStruct(s->NodeName(), outer);
}
s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
GlobalSymbols.AddSymbol(s->strct->Symbol); syms->AddSymbol(s->strct->Symbol);
for (auto e : s->Enums) for (auto e : s->Enums)
{ {
@ -577,7 +600,7 @@ void ZCCCompiler::CreateClassTypes()
if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName()); if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName());
c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.) c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.)
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol); OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c); Classes.Push(c);
OrigClasses.Delete(i--); OrigClasses.Delete(i--);
donesomething = true; donesomething = true;
@ -601,7 +624,7 @@ void ZCCCompiler::CreateClassTypes()
// create a placeholder so that the compiler can continue looking for errors. // create a placeholder so that the compiler can continue looking for errors.
c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()); c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol); OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c); Classes.Push(c);
OrigClasses.Delete(i--); OrigClasses.Delete(i--);
donesomething = true; donesomething = true;
@ -617,7 +640,7 @@ void ZCCCompiler::CreateClassTypes()
Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars()); Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars());
c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()); c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol); OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c); Classes.Push(c);
} }
@ -678,7 +701,7 @@ void ZCCCompiler::CompileAllConstants()
// put all constants in one list to make resolving this easier. // put all constants in one list to make resolving this easier.
TArray<ZCC_ConstantWork> constantwork; TArray<ZCC_ConstantWork> constantwork;
CopyConstants(constantwork, Constants, nullptr, OutputSymbols); CopyConstants(constantwork, Constants, nullptr, &OutNamespace->Symbols);
for (auto c : Classes) for (auto c : Classes)
{ {
CopyConstants(constantwork, c->Constants, c->Type(), &c->Type()->Symbols); CopyConstants(constantwork, c->Constants, c->Type(), &c->Type()->Symbols);
@ -810,7 +833,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work) bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work)
{ {
FCompileContext ctx(work->cls, false); FCompileContext ctx(OutNamespace, work->cls, false);
FxExpression *exp = ConvertNode(work->node->Value); FxExpression *exp = ConvertNode(work->node->Value);
try try
{ {
@ -836,49 +859,6 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work)
} }
//==========================================================================
//
// ZCCCompiler :: IdentifyIdentifier
//
// Returns a node that represents what the identifer stands for.
//
//==========================================================================
ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *symt)
{
// Check the symbol table for the identifier.
PSymbolTable *table;
PSymbol *sym = symt->FindSymbolInTable(idnode->Identifier, table);
// GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly.
if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(idnode->Identifier, table);
if (sym != nullptr)
{
ZCC_Expression *node = NodeFromSymbol(sym, idnode, table);
if (node != NULL)
{
return node;
}
}
else if (SimplifyingConstant) // leave unknown identifiers alone when simplifying non-constants. It is impossible to know what they are here.
{
// Also handle line specials.
// To call this like a function this needs to be done differently, but for resolving constants this is ok.
int spec = P_FindLineSpecial(FName(idnode->Identifier).GetChars());
if (spec != 0)
{
ZCC_ExprConstant *val = static_cast<ZCC_ExprConstant *>(AST.InitNode(sizeof(*val), AST_ExprConstant, idnode));
val->Operation = PEX_ConstValue;
val->Type = TypeSInt32;
val->IntVal = spec;
return val;
}
Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars());
idnode->ToErrorNode();
}
return idnode;
}
//========================================================================== //==========================================================================
// //
// ZCCCompiler :: NodeFromSymbol // ZCCCompiler :: NodeFromSymbol
@ -1056,6 +1036,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
{ {
auto field = Fields[0]; auto field = Fields[0];
FieldDesc *fd = nullptr; FieldDesc *fd = nullptr;
FString str = FName(field->Names[0].Name).GetChars();
PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true); PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true);
@ -1394,10 +1375,15 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
} }
else else
{ {
// This doesn't check the class list directly but the current symbol table to ensure that
// this does not reference a type that got shadowed by a more local definition.
// We first look in the current class and its parents, and then in the current namespace and its parents.
auto sym = outertype->Symbols.FindSymbol(ctype->Restriction->Id, true); auto sym = outertype->Symbols.FindSymbol(ctype->Restriction->Id, true);
if (sym == nullptr) sym = GlobalSymbols.FindSymbol(ctype->Restriction->Id, false); if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(ctype->Restriction->Id, true);
if (sym == nullptr) if (sym == nullptr)
{ {
// A symbol with a given name cannot be reached from this definition point, so
// even if a class with the given name exists, it is not accessible.
Error(field, "%s: Unknown identifier", FName(ctype->Restriction->Id).GetChars()); Error(field, "%s: Unknown identifier", FName(ctype->Restriction->Id).GetChars());
return TypeError; return TypeError;
} }
@ -1434,10 +1420,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
{ {
// Check the symbol table for the identifier. // Check the symbol table for the identifier.
PSymbolTable *table; PSymbol *sym = symt->FindSymbol(type->UserType->Id, true);
PSymbol *sym = symt->FindSymbolInTable(type->UserType->Id, table); // We first look in the current class and its parents, and then in the current namespace and its parents.
// GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly. if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(type->UserType->Id, true);
if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table);
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{ {
auto ptype = static_cast<PSymbolType *>(sym)->Type; auto ptype = static_cast<PSymbolType *>(sym)->Type;
@ -1477,7 +1462,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
} while (node != arraysize); } while (node != arraysize);
FCompileContext ctx(cls, false); FCompileContext ctx(OutNamespace, cls, false);
for (auto node : indices) for (auto node : indices)
{ {
// There is no float->int casting here. // There is no float->int casting here.
@ -1526,7 +1511,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper
const char * p = prop->params; const char * p = prop->params;
auto exp = property->Values; auto exp = property->Values;
FCompileContext ctx(bag.Info, false); FCompileContext ctx(OutNamespace, bag.Info, false);
while (true) while (true)
{ {
FPropParam conv; FPropParam conv;
@ -1693,7 +1678,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
} }
auto exp = property->Values; auto exp = property->Values;
FCompileContext ctx(bag.Info, false); FCompileContext ctx(OutNamespace, bag.Info, false);
for (auto f : prop->Variables) for (auto f : prop->Variables)
{ {
void *addr; void *addr;
@ -1775,7 +1760,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro
if (namenode->Id == NAME_DamageFunction) if (namenode->Id == NAME_DamageFunction)
{ {
auto x = ConvertNode(prop->Values); auto x = ConvertNode(prop->Values);
CreateDamageFunction(cls, (AActor *)bag.Info->Defaults, x, false, Lump); CreateDamageFunction(OutNamespace, cls, (AActor *)bag.Info->Defaults, x, false, Lump);
((AActor *)bag.Info->Defaults)->DamageVal = -1; ((AActor *)bag.Info->Defaults)->DamageVal = -1;
return; return;
} }
@ -1923,6 +1908,7 @@ void ZCCCompiler::InitDefaults()
#ifdef _DEBUG #ifdef _DEBUG
bag.ClassName = c->Type()->TypeName; bag.ClassName = c->Type()->TypeName;
#endif #endif
bag.Namespace = OutNamespace;
bag.Info = ti; bag.Info = ti;
bag.DropItemSet = false; bag.DropItemSet = false;
bag.StateSet = false; bag.StateSet = false;
@ -2150,7 +2136,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
// It will also lose important type info about enums, once these get implemented // It will also lose important type info about enums, once these get implemented
// The code generator can do this properly for us. // The code generator can do this properly for us.
FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false);
FCompileContext ctx(c->Type(), false); FCompileContext ctx(OutNamespace, c->Type(), false);
x = x->Resolve(ctx); x = x->Resolve(ctx);
if (x != nullptr) if (x != nullptr)
@ -2258,7 +2244,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
auto code = ConvertAST(c->Type(), f->Body); auto code = ConvertAST(c->Type(), f->Body);
if (code != nullptr) if (code != nullptr)
{ {
FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump); FunctionBuildList.AddFunction(OutNamespace, sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump);
} }
} }
} }
@ -2527,7 +2513,7 @@ void ZCCCompiler::CompileStates()
{ {
state.sprite = GetSpriteIndex(sl->Sprite->GetChars()); state.sprite = GetSpriteIndex(sl->Sprite->GetChars());
} }
FCompileContext ctx(c->Type(), false); FCompileContext ctx(OutNamespace, c->Type(), false);
if (CheckRandom(sl->Duration)) if (CheckRandom(sl->Duration))
{ {
auto func = static_cast<ZCC_ExprFuncCall *>(sl->Duration); auto func = static_cast<ZCC_ExprFuncCall *>(sl->Duration);
@ -2581,7 +2567,7 @@ void ZCCCompiler::CompileStates()
if (code != nullptr) if (code != nullptr)
{ {
auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags); auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags);
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump); state.ActionFunc = FunctionBuildList.AddFunction(OutNamespace, funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump);
} }
} }

View file

@ -86,13 +86,13 @@ struct ZCC_ConstantWork
class ZCCCompiler class ZCCCompiler
{ {
public: public:
ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PSymbolTable &outsymbols, int lumpnum); ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PNamespace *outnamespace, int lumpnum);
~ZCCCompiler(); ~ZCCCompiler();
int Compile(); int Compile();
private: private:
int IntConstFromNode(ZCC_TreeNode *node, PStruct *cls); int IntConstFromNode(ZCC_TreeNode *node, PStruct *cls);
FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls); FString StringConstFromNode(ZCC_TreeNode *node, PStruct *cls);
void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode);
void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer);
void CreateStructTypes(); void CreateStructTypes();
@ -130,7 +130,6 @@ private:
PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false); PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false);
ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *sym);
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table); ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table);
ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode); ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode); ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
@ -147,7 +146,7 @@ private:
DObject *Outer; DObject *Outer;
PStruct *ConvertClass; // class type to be used when resoving symbols while converting an AST PStruct *ConvertClass; // class type to be used when resoving symbols while converting an AST
PSymbolTable *GlobalTreeNodes; PSymbolTable *GlobalTreeNodes;
PSymbolTable *OutputSymbols; PNamespace *OutNamespace;
ZCC_AST &AST; ZCC_AST &AST;
int Lump; int Lump;
}; };

View file

@ -226,6 +226,8 @@ static void InitTokenMap()
#undef TOKENDEF #undef TOKENDEF
#undef TOKENDEF2 #undef TOKENDEF2
//**--------------------------------------------------------------------------
static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state) static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state)
{ {
int tokentype; int tokentype;
@ -311,6 +313,8 @@ parse_end:
state.sc = nullptr; state.sc = nullptr;
} }
//**--------------------------------------------------------------------------
static void DoParse(int lumpnum) static void DoParse(int lumpnum)
{ {
FScanner sc; FScanner sc;
@ -395,7 +399,8 @@ static void DoParse(int lumpnum)
} }
PSymbolTable symtable; PSymbolTable symtable;
ZCCCompiler cc(state, NULL, symtable, GlobalSymbols, lumpnum); auto newns = Wads.GetLumpFile(lumpnum) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(lumpnum));
ZCCCompiler cc(state, NULL, symtable, newns, lumpnum);
cc.Compile(); cc.Compile();
if (FScriptPosition::ErrorCounter > 0) if (FScriptPosition::ErrorCounter > 0)

View file

@ -305,7 +305,7 @@ enum EPickStart
} }
// Although String is a builtin type, this is a convenient way to attach methods to it. // Although String is a builtin type, this is a convenient way to attach methods to it.
struct String native struct StringStruct native
{ {
native void Replace(String pattern, String replacement); native void Replace(String pattern, String replacement);
native static vararg String Format(String fmt, ...); native static vararg String Format(String fmt, ...);

View file

@ -127,7 +127,7 @@ extend class PlayerPawn
{ {
let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup")); let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup"));
armoritem.SaveAmount = 100*deh.BlueAC; armoritem.SaveAmount = 100*deh.BlueAC;
armoritem.SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : 0.5; armoritem.SavePercent = gameinfo.Armor2Percent > 0 ? gameinfo.Armor2Percent * 100 : 50;
if (!armoritem.CallTryPickup (self)) if (!armoritem.CallTryPickup (self))
{ {
armoritem.Destroy (); armoritem.Destroy ();