- fixed: Class and struct name lookup was not context aware.

If a later module reused an existing name for a different class or struct type, this new name would completely shadow the old one, even in the base files.
Changed it so that each compilation unit (i.e. each ZScript and DECORATE lump) get their own symbol table and can only see the symbol tables that got defined in lower numbered resource files so that later definitions do not pollute the available list of symbols when running the compiler backend and code generator - which happens after everything has been parsed.

Another effect of this is that a mod that reuses the name of an internal global constant will only see its own constant, again reducing the risk of potential errors in case the internal definitions add some new values.

Global constants are still discouraged from being used because what this does not and can not handle is the case that a mod defines a global constant with the same name as a class variable. In such a case the class variable will always take precedence for code inside that class.

Note that the internal struct String had to be renamed for this because the stricter checks did not let the type String pass on the left side of a '.' anymore.

- made PEnum inherit from PInt and not from PNamedType.

The old inheritance broke nearly every check for integer compatibility in the compiler, so this hopefully leads to a working enum implementation.
This commit is contained in:
Christoph Oelckers 2017-01-23 19:09:36 +01:00
parent db4c5e090d
commit b3aa7c61a9
19 changed files with 295 additions and 221 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);
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,7 +86,7 @@ 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();
@ -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, ...);