Functions store their containing proplist instead of the C4AulScript

The C4AulScript containing the source of the function was already mostly
used to get the relevant proplist or available from context. This will
allow more than one proplist plus the global one per scripthost to contain
functions.
epoxy
Günther Brammer 2014-04-20 15:52:09 +02:00
parent d0d27d25f1
commit 507b63a55a
12 changed files with 53 additions and 65 deletions

View File

@ -2777,7 +2777,7 @@ void InitGameFunctionMap(C4AulScriptEngine *pEngine)
}
// add all def script funcs
for (C4ScriptFnDef *pDef = &C4ScriptGameFnMap[0]; pDef->Identifier; pDef++)
new C4AulDefFunc(pEngine, pDef);
new C4AulDefFunc(pEngine->GetPropList(), pDef);
#define F(f) AddFunc(pEngine, #f, Fn##f)
AddFunc(pEngine, "GetX", FnGetX);

View File

@ -111,8 +111,8 @@ std::string C4AulScript::Translate(const std::string &text) const
throw C4LangStringTable::NoSuchTranslation(text);
}
C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, C4ScriptHost *pOrgScript, const char *pName, const char *Script):
C4AulFunc(pOwner, pName),
C4AulScriptFunc::C4AulScriptFunc(C4PropListStatic * Parent, C4ScriptHost *pOrgScript, const char *pName, const char *Script):
C4AulFunc(Parent, pName),
OwnerOverloaded(NULL),
ParCount(0),
Script(Script),
@ -123,8 +123,8 @@ C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, C4ScriptHost *pOrgScript,
AddBCC(AB_EOFN);
}
C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, const C4AulScriptFunc &FromFunc):
C4AulFunc(pOwner, FromFunc.GetName()),
C4AulScriptFunc::C4AulScriptFunc(C4PropListStatic * Parent, const C4AulScriptFunc &FromFunc):
C4AulFunc(Parent, FromFunc.GetName()),
OwnerOverloaded(NULL),
ParCount(FromFunc.ParCount),
Script(FromFunc.Script),

View File

@ -194,8 +194,8 @@ public:
}
C4ScriptHost *pOrgScript; // the orginal script (!= Owner if included or appended)
C4AulScriptFunc(C4AulScript *pOwner, C4ScriptHost *pOrgScript, const char *pName, const char *Script);
C4AulScriptFunc(C4AulScript *pOwner, const C4AulScriptFunc &FromFunc); // copy script/code, etc from given func
C4AulScriptFunc(C4PropListStatic * Parent, C4ScriptHost *pOrgScript, const char *pName, const char *Script);
C4AulScriptFunc(C4PropListStatic * Parent, const C4AulScriptFunc &FromFunc); // copy script/code, etc from given func
~C4AulScriptFunc();
void ParseFn(C4AulScriptContext* context = NULL);

View File

@ -208,10 +208,10 @@ template <> struct C4ValueConv<int> : public C4ValueConv<int32_t> { };
class C4AulDefFuncHelper: public C4AulFunc
{
public:
C4AulDefFuncHelper(C4AulScript *pOwner, const char *pName, bool Public,
C4AulDefFuncHelper(C4PropListStatic * Parent, const char *pName, bool Public,
C4V_Type pt0 = C4V_Any, C4V_Type pt1 = C4V_Any, C4V_Type pt2 = C4V_Any, C4V_Type pt3 = C4V_Any, C4V_Type pt4 = C4V_Any,
C4V_Type pt5 = C4V_Any, C4V_Type pt6 = C4V_Any, C4V_Type pt7 = C4V_Any, C4V_Type pt8 = C4V_Any, C4V_Type pt9 = C4V_Any):
C4AulFunc(pOwner, pName),
C4AulFunc(Parent, pName),
Public(Public)
{
ParType[0] = pt0;
@ -224,7 +224,7 @@ public:
ParType[7] = pt7;
ParType[8] = pt8;
ParType[9] = pt9;
Owner->GetPropList()->SetPropertyByS(Name, C4VFunction(this));
Parent->SetPropertyByS(Name, C4VFunction(this));
}
~C4AulDefFuncHelper()
{
@ -272,8 +272,8 @@ public C4AulDefFuncHelper { \
virtual C4V_Type GetRetType() const \
{ return C4ValueConv<RType>::Type(); } \
/* Constructor, using the base class to create the ParType array */ \
C4AulDefFunc##N(C4AulScript *pOwner, const char *pName, Func pFunc, bool Public): \
C4AulDefFuncHelper(pOwner, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
C4AulDefFunc##N(C4PropListStatic * Parent, const char *pName, Func pFunc, bool Public): \
C4AulDefFuncHelper(Parent, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
/* Extracts the parameters from C4Values and wraps the return value in a C4Value */ \
virtual C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) \
{ return C4ValueConv<RType>::ToC4V(pFunc(_this LIST(N, CONV_FROM_C4V))); } \
@ -290,8 +290,8 @@ public C4AulDefFuncHelper { \
virtual C4V_Type GetRetType() const \
{ return C4ValueConv<RType>::Type(); } \
/* Constructor, using the base class to create the ParType array */ \
C4AulDefObjectFunc##N(C4AulScript *pOwner, const char *pName, Func pFunc, bool Public): \
C4AulDefFuncHelper(pOwner, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
C4AulDefObjectFunc##N(C4PropListStatic * Parent, const char *pName, Func pFunc, bool Public): \
C4AulDefFuncHelper(Parent, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
/* Extracts the parameters from C4Values and wraps the return value in a C4Value */ \
virtual C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) \
{ \
@ -304,12 +304,12 @@ public C4AulDefFuncHelper { \
template <typename RType LIST(N, TYPENAMES)> \
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4PropList * LIST(N, PARS)), bool Public=true) \
{ \
new C4AulDefFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
new C4AulDefFunc##N<RType LIST(N, PARS)>(pOwner->GetPropList(), Name, pFunc, Public); \
} \
template <typename RType LIST(N, TYPENAMES)> \
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4Object * LIST(N, PARS)), bool Public=true) \
{ \
new C4AulDefObjectFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
new C4AulDefObjectFunc##N<RType LIST(N, PARS)>(pOwner->GetPropList(), Name, pFunc, Public); \
}
TEMPLATE(0)
@ -361,7 +361,7 @@ class C4AulDefFunc : C4AulFunc
public:
C4ScriptFnDef* Def;
C4AulDefFunc(C4AulScript *pOwner, C4ScriptFnDef* pDef);
C4AulDefFunc(C4PropListStatic * Parent, C4ScriptFnDef* pDef);
~C4AulDefFunc();
virtual bool GetPublic() const { return !!Def->Public; }

View File

@ -76,7 +76,7 @@ StdStrBuf C4AulScriptContext::ReturnDump(StdStrBuf Dump)
Dump.AppendChar(')');
}
else
Dump.Append(Func->Owner->ScriptName);
Dump.Append(Func->Parent->GetDataString());
// Script
if (!fDirectExec && Func->pOrgScript)
Dump.AppendFormat(" (%s:%d)",
@ -1026,10 +1026,6 @@ void C4AulProfiler::Show()
C4Value C4AulScriptFunc::Exec(C4PropList * p, C4Value pPars[], bool fPassErrors)
{
// handle easiest case first
if (Owner->State != ASS_PARSED) return C4Value();
// execute
return AulExec.Exec(this, p, pPars, fPassErrors);
}
@ -1046,7 +1042,7 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
// profiler
AulExec.StartDirectExec();
// Add a new function
C4AulScriptFunc *pFunc = new C4AulScriptFunc(this, GetScriptHost(), 0, szScript);
C4AulScriptFunc *pFunc = new C4AulScriptFunc(GetPropList(), GetScriptHost(), 0, szScript);
// Parse function
try
{

View File

@ -19,12 +19,12 @@
#include <C4AulFunc.h>
#include <C4Aul.h>
C4AulFunc::C4AulFunc(C4AulScript *pOwner, const char *pName):
C4AulFunc::C4AulFunc(C4PropListStatic * Parent, const char *pName):
Parent(Parent),
iRefCnt(0),
Name(pName ? Strings.RegString(pName) : 0),
MapNext(NULL)
{
Owner = pOwner;
// add to global lookuptable with this name
if (GetName())
::ScriptEngine.FuncLookUp.Add(this);
@ -40,24 +40,19 @@ StdStrBuf C4AulFunc::GetFullName()
{
StdStrBuf r;
// "lost" function?
if (!Owner)
if (!Parent)
{
r.Ref("(unowned) ");
}
else if (Owner->GetPropList() && Owner->GetPropList()->IsStatic())
{
r.Take(Owner->GetPropList()->IsStatic()->GetDataString());
r.AppendChar('.');
}
else if (Owner->Engine == Owner)
{
r.Ref("Global.");
}
else
{
r.Ref("(unknown) ");
r.Take(Parent->GetDataString());
r.AppendChar('.');
}
r.Append(Name->GetData());
if (GetName())
r.Append(Name->GetData());
else
r.Append("(unnamed)");
return r;
}

View File

@ -54,13 +54,13 @@ class C4AulFunc
unsigned int iRefCnt;
public:
C4AulFunc(C4AulScript *pOwner, const char *pName);
C4AulFunc(C4PropListStatic * Parent, const char *pName);
// Add/Remove Reference
void IncRef() { iRefCnt++; }
void DecRef() { if (!--iRefCnt) delete this; }
C4AulScript *Owner; // owner
const C4PropListStatic * Parent;
const char * GetName() const { return Name ? Name->GetCStr() : 0; }
virtual StdStrBuf GetFullName(); // get a fully classified name (C4ID::Name) for debug output

View File

@ -130,7 +130,7 @@ public:
pLoopStack(NULL)
{ }
C4AulParse(C4AulScriptFunc * Fn, C4AulScriptContext* context, enum Type Type):
Fn(Fn), Host(Fn->pOrgScript), pOrgScript(Fn->pOrgScript), Engine(Fn->Owner->Engine),
Fn(Fn), Host(Fn->pOrgScript), pOrgScript(Fn->pOrgScript), Engine(pOrgScript->Engine),
SPos(Fn->Script), TokenSPos(SPos),
TokenType(ATT_INVALID),
Type(Type),
@ -239,7 +239,7 @@ void C4AulScript::Warn(const char *pMsg, ...)
// display it
warning.show();
// count warnings
++::ScriptEngine.warnCnt;
++Engine->warnCnt;
}
void C4AulParse::Warn(const char *pMsg, ...)
@ -253,7 +253,7 @@ void C4AulParse::Warn(const char *pMsg, ...)
if (pOrgScript != Host)
DebugLogF(" (as #appendto/#include to %s)", Host->ScriptName.getData());
// count warnings
++::ScriptEngine.warnCnt;
++Engine->warnCnt;
}
void C4AulParse::Error(const char *pMsg, ...)
@ -1405,7 +1405,7 @@ void C4AulParse::Parse_Script(C4ScriptHost * scripthost)
{
err.show();
// and count (visible only ;) )
++::ScriptEngine.errCnt;
++Engine->errCnt;
}
all_ok = false;
@ -1459,16 +1459,16 @@ void C4AulParse::Parse_Function()
Error("function definition: name already in use (global constant)");
}
// get script fn
C4AulScript * owner;
C4PropListStatic * Parent;
if (is_global)
owner = Engine;
Parent = Engine->GetPropList();
else
owner = Host;
Parent = Host->GetPropList();
Fn = 0;
C4AulFunc * f = owner->GetPropList()->GetFunc(Idtf);
C4AulFunc * f = Parent->GetFunc(Idtf);
while (f)
{
if (f->SFunc() && f->SFunc()->pOrgScript == pOrgScript && f->Owner == owner)
if (f->SFunc() && f->SFunc()->pOrgScript == pOrgScript && f->Parent == Parent)
{
if (Fn)
Warn("Duplicate function %s", Idtf);
@ -1479,9 +1479,9 @@ void C4AulParse::Parse_Function()
// first preparser run or a new func in a reloaded script
if (!Fn && Type == PREPARSER)
{
Fn = new C4AulScriptFunc(owner, pOrgScript, Idtf, SPos);
Fn->SetOverloaded(owner->GetPropList()->GetFunc(Fn->Name));
owner->GetPropList()->SetPropertyByS(Fn->Name, C4VFunction(Fn));
Fn = new C4AulScriptFunc(Parent, pOrgScript, Idtf, SPos);
Fn->SetOverloaded(Parent->GetFunc(Fn->Name));
Parent->SetPropertyByS(Fn->Name, C4VFunction(Fn));
}
assert(Fn);
if (Type == PREPARSER)
@ -2227,11 +2227,8 @@ void C4AulParse::Parse_Expression(int iParentPrio)
Shift();
}
// check for variable (local)
else if (Host && Host->LocalNamed.GetItemNr(Idtf) != -1)
else if (Host && Host->GetPropList() == Fn->Parent && Host->LocalNamed.GetItemNr(Idtf) != -1)
{
// global func?
if (Fn->Owner == &::ScriptEngine)
throw C4AulParseError(this, "using local variable in global function!");
// insert variable by id
C4String * pKey = Strings.RegString(Idtf);
AddBCC(AB_LOCALN, (intptr_t) pKey);
@ -2327,9 +2324,8 @@ void C4AulParse::Parse_Expression(int iParentPrio)
if (TokenType == ATT_BOPEN)
Parse_Params(10, NULL);
}
else if ((FoundFn = Fn->Owner->GetPropList()->GetFunc(Idtf)))
else if ((FoundFn = Fn->Parent->GetFunc(Idtf)))
{
assert(Host == Fn->Owner || Fn->Owner == Engine || (Host && !Host->GetPropList()));
if (Config.Developer.ExtraWarnings && !FoundFn->GetPublic())
Warn("using deprecated function %s", Idtf);
Shift();
@ -2899,7 +2895,7 @@ void C4ScriptHost::CopyPropList(C4Set<C4Property> & from, C4PropListStatic * to)
{
C4AulScriptFunc *sfc;
if (sf->pOrgScript != this)
sfc = new C4AulScriptFunc(this, *sf);
sfc = new C4AulScriptFunc(to, *sf);
else
sfc = sf;
sfc->SetOverloaded(to->GetFunc(sf->Name));

View File

@ -83,6 +83,7 @@ public:
// saved as a reference to a global constant?
virtual class C4PropListStatic * IsStatic() { return NULL; }
const class C4PropListStatic * IsStatic() const { return const_cast<C4PropList*>(this)->IsStatic(); }
// saved as a reference to separately saved objects?
virtual bool IsNumbered() const { return false; }
// some proplists have references that are not reference-counted

View File

@ -135,10 +135,10 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix)
return true;
}
C4AulDefFunc::C4AulDefFunc(C4AulScript *pOwner, C4ScriptFnDef* pDef):
C4AulFunc(pOwner, pDef->Identifier), Def(pDef)
C4AulDefFunc::C4AulDefFunc(C4PropListStatic * Parent, C4ScriptFnDef* pDef):
C4AulFunc(Parent, pDef->Identifier), Def(pDef)
{
Owner->GetPropList()->SetPropertyByS(Name, C4VFunction(this));
Parent->SetPropertyByS(Name, C4VFunction(this));
}
C4AulDefFunc::~C4AulDefFunc()
@ -812,7 +812,7 @@ void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
// add all def script funcs
for (C4ScriptFnDef *pDef = &C4ScriptFnMap[0]; pDef->Identifier; pDef++)
new C4AulDefFunc(pEngine, pDef);
new C4AulDefFunc(pEngine->GetPropList(), pDef);
#define F(f) AddFunc(pEngine, #f, Fn##f)
F(Abs);
F(Min);

View File

@ -327,10 +327,10 @@ void C4Value::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
{
if (!pComp->isCompiler())
{
C4PropList * p = getPropList();
const C4PropList * p = getPropList();
if (getFunction())
{
p = Data.Fn->Owner->GetPropList();
p = Data.Fn->Parent;
assert(p);
assert(p->GetFunc(Data.Fn->GetName()) == Data.Fn);
assert(p->IsStatic());

View File

@ -83,7 +83,7 @@ TEST(DirectExecTest, HostUnmodifedByParseTest)
TestHost host2 = host;
host.test_equality(host2);
char szScript[] = "8*5";
C4AulScriptFunc *pFunc = new C4AulScriptFunc(&host, host.GetScriptHost(), 0, szScript);
C4AulScriptFunc *pFunc = new C4AulScriptFunc(host.GetPropList(), host.GetScriptHost(), 0, szScript);
host.test_equality(host2);
pFunc->ParseFn();
host.test_equality(host2);