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 global symbols
GlobalSymbols.MarkSymbols();
Namespaces.MarkSymbols();
// Mark bot stuff.
Mark(bglobal.firstthing);
Mark(bglobal.body1);

View file

@ -65,8 +65,9 @@ EXTERN_CVAR(Bool, strictdecorate);
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FNamespaceManager Namespaces;
FTypeTable TypeTable;
PSymbolTable GlobalSymbols;
TArray<PClass *> PClass::AllClasses;
bool PClass::bShutdown;
bool PClass::bVMOperational;
@ -117,7 +118,7 @@ void DumpTypeTable()
Printf("%4zu:", i);
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++;
all++;
}
@ -434,7 +435,7 @@ void PType::StaticInit()
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.
TypeStringStruct = NewNativeStruct(NAME_String, nullptr);
TypeStringStruct = NewNativeStruct("Stringstruct", nullptr);
#ifdef __BIG_ENDIAN__
TypeColorStruct->AddField(NAME_a, TypeUInt8);
TypeColorStruct->AddField(NAME_r, TypeUInt8);
@ -472,24 +473,24 @@ void PType::StaticInit()
GlobalSymbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_uShort, TypeUInt16));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Int, TypeSInt32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_uInt, TypeUInt32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Bool, TypeBool));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Double, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float32, TypeFloat32));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Float64, TypeFloat64));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_String, TypeString));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Name, TypeName));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_State, TypeState));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2));
GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uShort, TypeUInt16));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Int, TypeSInt32));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uInt, TypeUInt32));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Bool, TypeBool));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float, TypeFloat64));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Double, TypeFloat64));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float32, TypeFloat32));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float64, TypeFloat64));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_String, TypeString));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Name, TypeName));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_State, TypeState));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2));
Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3));
}
@ -1692,7 +1693,7 @@ PClassPointer *NewClassPointer(PClass *restrict)
IMPLEMENT_CLASS(PEnum, false, true)
IMPLEMENT_POINTERS_START(PEnum)
IMPLEMENT_POINTER(ValueType)
IMPLEMENT_POINTER(Outer)
IMPLEMENT_POINTERS_END
//==========================================================================
@ -1702,7 +1703,7 @@ IMPLEMENT_POINTERS_END
//==========================================================================
PEnum::PEnum()
: ValueType(NULL)
: PInt(4, false)
{
mDescriptiveName = "Enum";
}
@ -1714,8 +1715,10 @@ PEnum::PEnum()
//==========================================================================
PEnum::PEnum(FName name, PTypeBase *outer)
: PNamedType(name, outer), ValueType(NULL)
: PInt(4, false)
{
EnumName = name;
Outer = outer;
mDescriptiveName.Format("Enum<%s>", name.GetChars());
}
@ -1731,6 +1734,7 @@ PEnum::PEnum(FName name, PTypeBase *outer)
PEnum *NewEnum(FName name, PTypeBase *outer)
{
size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket);
if (etype == NULL)
{
@ -2373,6 +2377,7 @@ size_t PStruct::PropagateMark()
PStruct *NewStruct(FName name, PTypeBase *outer)
{
size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket);
if (stype == NULL)
{
@ -2392,8 +2397,8 @@ IMPLEMENT_CLASS(PNativeStruct, false, false)
//
//==========================================================================
PNativeStruct::PNativeStruct(FName name)
: PStruct(name, nullptr)
PNativeStruct::PNativeStruct(FName name, PTypeBase *outer)
: PStruct(name, outer)
{
mDescriptiveName.Format("NativeStruct<%s>", name.GetChars());
Size = 0;
@ -2411,10 +2416,11 @@ PNativeStruct::PNativeStruct(FName name)
PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer)
{
size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket);
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);
}
return static_cast<PNativeStruct *>(stype);
@ -2796,6 +2802,7 @@ void PClass::StaticInit ()
atterm (StaticShutdown);
StaticBootstrap();
Namespaces.GlobalNamespace = Namespaces.NewNamespace(0);
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.
TypeTable.Clear();
GlobalSymbols.ReleaseSymbols();
Namespaces.ReleaseSymbols();
for (i = 0; i < PClass::AllClasses.Size(); ++i)
{
@ -3039,14 +3046,14 @@ void PClass::InsertIntoHash ()
size_t bucket;
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)
{ // This type has already been inserted
I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
}
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 static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass),
/*FIXME:Outer*/0, zaname, NULL));
return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), 0, zaname, NULL));
}
//==========================================================================
@ -3376,7 +3382,7 @@ PClass *PClass::FindClassTentative(FName name)
Derive(type, name);
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;
}
@ -3835,3 +3841,60 @@ PSymbol *PSymbolTable::ReplaceSymbol(PSymbol *newsym)
Symbols.Insert(newsym->SymbolName, newsym);
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) {}
};
extern PSymbolTable GlobalSymbols;
// Basic information shared by all types ------------------------------------
// Only one copy of a type is ever instantiated at one time.
@ -593,15 +591,15 @@ protected:
// Compound types -----------------------------------------------------------
class PEnum : public PNamedType
class PEnum : public PInt
{
DECLARE_CLASS(PEnum, PNamedType);
DECLARE_CLASS(PEnum, PInt);
HAS_OBJECT_POINTERS;
public:
PEnum(FName name, PTypeBase *outer);
PType *ValueType;
TMap<FName, int> Values;
PTypeBase *Outer;
FName EnumName;
protected:
PEnum();
};
@ -710,7 +708,7 @@ class PNativeStruct : public PStruct
{
DECLARE_CLASS(PNativeStruct, PStruct);
public:
PNativeStruct(FName name = NAME_None);
PNativeStruct(FName name = NAME_None, PTypeBase *outer = nullptr);
};
class PPrototype : public PCompoundType
@ -986,31 +984,39 @@ public:
PSymbolConstString() {}
};
// Enumerations for serializing types in an archive -------------------------
// Namespaces --------------------------------------------------
enum ETypeVal : BYTE
class PNamespace : public PTypeBase
{
VAL_Int8,
VAL_UInt8,
VAL_Int16,
VAL_UInt16,
VAL_Int32,
VAL_UInt32,
VAL_Int64,
VAL_UInt64,
VAL_Zero,
VAL_One,
VAL_Float32,
VAL_Float64,
VAL_String,
VAL_Name,
VAL_Struct,
VAL_Array,
VAL_Object,
VAL_State,
VAL_Class,
DECLARE_CLASS(PNamespace, PTypeBase)
HAS_OBJECT_POINTERS;
public:
PSymbolTable Symbols;
PNamespace *Parent;
int FileNum; // This is for blocking DECORATE access to later files.
PNamespace() {}
PNamespace(int filenum, PNamespace *parent);
size_t PropagateMark();
};
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)
{
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)
: ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(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), CurGlobals(cg)
{
if (fnc != nullptr) Class = fnc->OwningClass;
}
FCompileContext::FCompileContext(PStruct *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1)
FCompileContext::FCompileContext(PNamespace *cg, PStruct *cls, bool fromdecorate)
: 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)
{
return GlobalSymbols.FindSymbol(identifier, true);
return CurGlobals->Symbols.FindSymbol(identifier, true);
}
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);
if (ccls == nullptr)
auto sym = ctx.Class->Symbols.FindSymbol(name, true);
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));
if (ccls == nullptr) ccls = dyn_cast<PStruct>(TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), 0, (intptr_t)name, nullptr));
auto type = static_cast<PSymbolType*>(sym);
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
@ -235,7 +249,7 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
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)
{
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
@ -243,7 +257,7 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall
calldec->PrintableName = funcname.GetChars();
symfunc->Function = calldec;
sym = symfunc;
GlobalSymbols.AddSymbol(sym);
Namespaces.GlobalNamespace->Symbols.AddSymbol(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
// 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;
}
@ -7256,7 +7270,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(ctx);
}
PClass *cls = PClass::FindClass(MethodName);
PClass *cls = FindClassType(MethodName, ctx);
if (cls != nullptr && cls->bExported)
{
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
@ -7487,9 +7501,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
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
// 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;
}
@ -7500,8 +7516,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (ccls != nullptr)
{
// [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)
{
cls = ccls;
@ -9977,7 +9991,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
if (clsname != NAME_None)
{
cls = PClass::FindClass(clsname);
cls = FindClassType(clsname, ctx);
if (cls == nullptr)
{
/* lax */

View file

@ -84,9 +84,10 @@ struct FCompileContext
int Lump;
bool Unsafe = false;
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
PNamespace *CurGlobals;
FCompileContext(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, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump);
FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(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);
void ParseOldDecoration(FScanner &sc, EDefinitionType def)
void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
{
Baggage bag;
TArray<FState> StateArray;
@ -116,6 +116,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
typeName = FName(sc.String);
type = DecoDerivedClass(FScriptPosition(sc), parent, typeName);
ResetBaggage(&bag, parent);
bag.Namespace = ns;
bag.Info = type;
bag.fromDecorate = true;
#ifdef _DEBUG

View file

@ -82,13 +82,13 @@ static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls);
static FxExpression *ParseExpressionA (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);
if (mustresolve)
if (spc)
{
FCompileContext ctx(cls, true);
FCompileContext ctx(spc, cls, true);
data = data->Resolve(ctx);
}

View file

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

View file

@ -343,7 +343,7 @@ endofstate:
if (ScriptCode != nullptr)
{
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);
if (count < 0)
@ -671,7 +671,7 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression
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);
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)
{
@ -226,7 +226,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
{
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
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
FString ClassName; // This is here so that during debugging the class name can be seen
#endif
PNamespace *Namespace;
PClassActor *Info;
bool DropItemSet;
bool StateSet;
@ -132,7 +133,7 @@ struct Baggage
inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
{
bag->DropItemList = NULL;
bag->DropItemList = nullptr;
bag->DropItemSet = false;
bag->CurrentState = 0;
bag->fromDecorate = true;
@ -150,7 +151,7 @@ AFuncDesc *FindFunction(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 ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression *> &out_params,
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);
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
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);
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant);
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type);
enum

View file

@ -762,16 +762,16 @@ void InitThingdef()
// expose the global validcount variable.
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.
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
PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr);
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.
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);
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
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
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
PStruct *gistruct = NewNativeStruct("GameInfoStruct", nullptr);
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.
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
@ -801,33 +801,33 @@ void InitThingdef()
pstruct->Align = alignof(player_t);
PArray *parray = NewArray(pstruct, MAXPLAYERS);
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);
parray = NewArray(TypeBool, MAXPLAYERS);
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);
GlobalSymbols.AddSymbol(playerf);
Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
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);
GlobalSymbols.AddSymbol(playerf);
Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf);
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.
// 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!!!
static AWeapon *wpnochg = WP_NOCHANGE;
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.
for (auto &fl : FlagLists)
@ -936,7 +936,7 @@ DEFINE_ACTION_FUNCTION(FStringTable, Localize)
ACTION_RETURN_STRING(GStrings(&label[1]));
}
DEFINE_ACTION_FUNCTION(FString, Replace)
DEFINE_ACTION_FUNCTION(FStringStruct, Replace)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_STRING(s1);
@ -1103,14 +1103,14 @@ static FString FStringFormat(VM_ARGS)
return output;
}
DEFINE_ACTION_FUNCTION(FString, Format)
DEFINE_ACTION_FUNCTION(FStringStruct, Format)
{
PARAM_PROLOGUE;
FString s = FStringFormat(param, defaultparam, numparam, ret, numret);
ACTION_RETURN_STRING(s);
}
DEFINE_ACTION_FUNCTION(FString, AppendFormat)
DEFINE_ACTION_FUNCTION(FStringStruct, AppendFormat)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
// first parameter is the self pointer

View file

@ -689,7 +689,7 @@ DEFINE_PROPERTY(damage, X, Actor)
defaults->DamageVal = dmgval;
// 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;
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();
if (func != nullptr)
@ -814,6 +814,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
//Printf("Adding %s\n", name.GetChars());
Item it;
assert(gnspc != nullptr);
it.CurGlobals = gnspc;
it.Func = functype;
it.Code = code;
it.PrintableName = name;
@ -853,7 +855,7 @@ void FFunctionBuildList::Build()
assert(item.Code != NULL);
// 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.
VMFunctionBuilder buildit(item.Func->GetImplicitArgs());

View file

@ -141,6 +141,7 @@ class FFunctionBuildList
FxExpression *Code = nullptr;
PPrototype *Proto = nullptr;
VMScriptFunction *Function = nullptr;
PNamespace *CurGlobals = nullptr;
FString PrintableName;
int StateIndex;
int StateCount;
@ -151,7 +152,7 @@ class FFunctionBuildList
TArray<Item> mItems;
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();
};

View file

@ -74,7 +74,7 @@ static FString GetStringConst(FxExpression *ex, FCompileContext &ctx)
int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls)
{
FCompileContext ctx(cls, false);
FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxIntCast(ConvertNode(node), false);
ex = ex->Resolve(ctx);
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)
{
FCompileContext ctx(cls, false);
FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxStringCast(ConvertNode(node));
ex = ex->Resolve(ctx);
if (ex == nullptr) return "";
@ -155,6 +155,11 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
break;
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);
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)
: Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), Lump(lumpnum)
ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PNamespace *_outnamespc, int lumpnum)
: Outer(_outer), GlobalTreeNodes(&_symbols), OutNamespace(_outnamespc), AST(ast), Lump(lumpnum)
{
FScriptPosition::ResetErrorCounter();
// Group top-level nodes by type
@ -303,8 +308,8 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols,
{
case AST_Enum:
zenumType = static_cast<ZCC_Enum *>(node);
enumType = NewEnum(zenumType->NodeName, nullptr);
GlobalSymbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType));
enumType = NewEnum(zenumType->NodeName, OutNamespace);
OutNamespace->Symbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType));
break;
case AST_Class:
@ -468,13 +473,31 @@ void ZCCCompiler::CreateStructTypes()
{
for(auto s : Structs)
{
PTypeBase *outer;
PSymbolTable *syms;
s->Outer = s->OuterDef == nullptr? nullptr : s->OuterDef->CType();
if (s->strct->Flags & ZCC_Native)
s->strct->Type = NewNativeStruct(s->NodeName(), nullptr);
if (s->Outer)
{
outer = s->Outer;
syms = &s->Outer->Symbols;
}
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());
GlobalSymbols.AddSymbol(s->strct->Symbol);
syms->AddSymbol(s->strct->Symbol);
for (auto e : s->Enums)
{
@ -577,7 +600,7 @@ void ZCCCompiler::CreateClassTypes()
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->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol);
OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c);
OrigClasses.Delete(i--);
donesomething = true;
@ -601,7 +624,7 @@ void ZCCCompiler::CreateClassTypes()
// create a placeholder so that the compiler can continue looking for errors.
c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol);
OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c);
OrigClasses.Delete(i--);
donesomething = true;
@ -617,7 +640,7 @@ void ZCCCompiler::CreateClassTypes()
Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars());
c->cls->Type = RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName());
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
GlobalSymbols.AddSymbol(c->cls->Symbol);
OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c);
}
@ -678,7 +701,7 @@ void ZCCCompiler::CompileAllConstants()
// put all constants in one list to make resolving this easier.
TArray<ZCC_ConstantWork> constantwork;
CopyConstants(constantwork, Constants, nullptr, OutputSymbols);
CopyConstants(constantwork, Constants, nullptr, &OutNamespace->Symbols);
for (auto c : Classes)
{
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)
{
FCompileContext ctx(work->cls, false);
FCompileContext ctx(OutNamespace, work->cls, false);
FxExpression *exp = ConvertNode(work->node->Value);
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
@ -1056,6 +1036,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
{
auto field = Fields[0];
FieldDesc *fd = nullptr;
FString str = FName(field->Names[0].Name).GetChars();
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
{
// 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);
if (sym == nullptr) sym = GlobalSymbols.FindSymbol(ctype->Restriction->Id, false);
if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(ctype->Restriction->Id, true);
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());
return TypeError;
}
@ -1434,10 +1420,9 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
{
// Check the symbol table for the identifier.
PSymbolTable *table;
PSymbol *sym = symt->FindSymbolInTable(type->UserType->Id, 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(type->UserType->Id, table);
PSymbol *sym = symt->FindSymbol(type->UserType->Id, true);
// We first look in the current class and its parents, and then in the current namespace and its parents.
if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(type->UserType->Id, true);
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto ptype = static_cast<PSymbolType *>(sym)->Type;
@ -1477,7 +1462,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
} while (node != arraysize);
FCompileContext ctx(cls, false);
FCompileContext ctx(OutNamespace, cls, false);
for (auto node : indices)
{
// There is no float->int casting here.
@ -1526,7 +1511,7 @@ void ZCCCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *proper
const char * p = prop->params;
auto exp = property->Values;
FCompileContext ctx(bag.Info, false);
FCompileContext ctx(OutNamespace, bag.Info, false);
while (true)
{
FPropParam conv;
@ -1693,7 +1678,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
}
auto exp = property->Values;
FCompileContext ctx(bag.Info, false);
FCompileContext ctx(OutNamespace, bag.Info, false);
for (auto f : prop->Variables)
{
void *addr;
@ -1775,7 +1760,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro
if (namenode->Id == NAME_DamageFunction)
{
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;
return;
}
@ -1923,6 +1908,7 @@ void ZCCCompiler::InitDefaults()
#ifdef _DEBUG
bag.ClassName = c->Type()->TypeName;
#endif
bag.Namespace = OutNamespace;
bag.Info = ti;
bag.DropItemSet = 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
// The code generator can do this properly for us.
FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false);
FCompileContext ctx(c->Type(), false);
FCompileContext ctx(OutNamespace, c->Type(), false);
x = x->Resolve(ctx);
if (x != nullptr)
@ -2258,7 +2244,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
auto code = ConvertAST(c->Type(), f->Body);
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());
}
FCompileContext ctx(c->Type(), false);
FCompileContext ctx(OutNamespace, c->Type(), false);
if (CheckRandom(sl->Duration))
{
auto func = static_cast<ZCC_ExprFuncCall *>(sl->Duration);
@ -2581,7 +2567,7 @@ void ZCCCompiler::CompileStates()
if (code != nullptr)
{
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
{
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();
int Compile();
private:
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 ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer);
void CreateStructTypes();
@ -130,7 +130,6 @@ private:
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_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
@ -147,7 +146,7 @@ private:
DObject *Outer;
PStruct *ConvertClass; // class type to be used when resoving symbols while converting an AST
PSymbolTable *GlobalTreeNodes;
PSymbolTable *OutputSymbols;
PNamespace *OutNamespace;
ZCC_AST &AST;
int Lump;
};

View file

@ -226,6 +226,8 @@ static void InitTokenMap()
#undef TOKENDEF
#undef TOKENDEF2
//**--------------------------------------------------------------------------
static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state)
{
int tokentype;
@ -311,6 +313,8 @@ parse_end:
state.sc = nullptr;
}
//**--------------------------------------------------------------------------
static void DoParse(int lumpnum)
{
FScanner sc;
@ -395,7 +399,8 @@ static void DoParse(int lumpnum)
}
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();
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.
struct String native
struct StringStruct native
{
native void Replace(String pattern, String replacement);
native static vararg String Format(String fmt, ...);

View file

@ -127,7 +127,7 @@ extend class PlayerPawn
{
let armoritem = BasicArmorPickup(Spawn("BasicArmorPickup"));
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))
{
armoritem.Destroy ();