forked from Mirrors/openclonk
Move Parser from C4AulScript to C4ScriptHost
parent
843642271d
commit
f166fdaed7
|
@ -110,6 +110,7 @@ class C4RegionList;
|
|||
class C4RoundResult;
|
||||
class C4RoundResults;
|
||||
class C4Scenario;
|
||||
class C4ScriptHost;
|
||||
class C4SoundSystem;
|
||||
class C4Stream;
|
||||
class C4String;
|
||||
|
|
|
@ -153,14 +153,11 @@ C4AulScript::C4AulScript()
|
|||
{
|
||||
// not compiled
|
||||
State = ASS_NONE;
|
||||
Script = NULL;
|
||||
Code.clear();
|
||||
LastCode = NULL;
|
||||
IncludesResolved = false;
|
||||
|
||||
// defaults
|
||||
Strict = MAXSTRICT;
|
||||
Preparsing=Resolving=false;
|
||||
Resolving=false;
|
||||
Temporary = false;
|
||||
LocalNamed.Reset();
|
||||
|
||||
|
@ -171,8 +168,6 @@ C4AulScript::C4AulScript()
|
|||
// prepare include list
|
||||
Includes.clear();
|
||||
Appends.clear();
|
||||
|
||||
stringTable = 0;
|
||||
}
|
||||
|
||||
C4AulScript::~C4AulScript()
|
||||
|
@ -202,9 +197,6 @@ void C4AulScript::Clear()
|
|||
while (Child0) // Child0->Unreg();
|
||||
if (Child0->Delete()) delete Child0; else Child0->Unreg();
|
||||
while (Func0) delete Func0;
|
||||
// delete script+code
|
||||
Script.Clear();
|
||||
ClearCode();
|
||||
// reset flags
|
||||
State = ASS_NONE;
|
||||
}
|
||||
|
|
|
@ -211,6 +211,7 @@ class C4AulFunc
|
|||
friend class C4AulScriptEngine;
|
||||
friend class C4AulFuncMap;
|
||||
friend class C4AulParseState;
|
||||
friend class C4ScriptHost;
|
||||
|
||||
public:
|
||||
C4AulFunc(C4AulScript *pOwner, const char *pName, bool bAtEnd = true); // constructor
|
||||
|
@ -260,7 +261,7 @@ public:
|
|||
C4ValueMapNames ParNamed; // list of named pars in this function
|
||||
int ParCount;
|
||||
C4V_Type ParType[C4AUL_MAX_Par]; // parameter types
|
||||
C4AulScript *pOrgScript; // the orginal script (!= Owner if included or appended)
|
||||
C4ScriptHost *pOrgScript; // the orginal script (!= Owner if included or appended)
|
||||
|
||||
C4AulScriptFunc(C4AulScript *pOwner, const char *pName, bool bAtEnd = true) : C4AulFunc(pOwner, pName, bAtEnd),
|
||||
OwnerOverloaded(NULL), ParCount(0),
|
||||
|
@ -270,6 +271,7 @@ public:
|
|||
ParNamed.Reset(); // safety :)
|
||||
} // constructor
|
||||
|
||||
void ParseFn(bool fExprOnly = false, C4AulScriptContext* context = NULL);
|
||||
virtual void UnLink();
|
||||
|
||||
virtual bool GetPublic() { return true; }
|
||||
|
@ -286,11 +288,11 @@ public:
|
|||
StdStrBuf GetFullName(); // get a fully classified name (C4ID::Name) for debug output
|
||||
int GetLineOfCode(C4AulBCC * bcc);
|
||||
C4AulBCC * GetCode();
|
||||
C4AulScript * GetCodeOwner();
|
||||
C4ScriptHost * GetCodeOwner();
|
||||
|
||||
time_t tProfileTime; // internally set by profiler
|
||||
|
||||
friend class C4AulScript;
|
||||
friend class C4ScriptHost;
|
||||
};
|
||||
|
||||
// defined function class
|
||||
|
@ -370,11 +372,6 @@ public:
|
|||
// script class
|
||||
class C4AulScript
|
||||
{
|
||||
// MSVC maybe needs this.
|
||||
#ifdef _MSC_VER
|
||||
friend class C4AulScript;
|
||||
#endif
|
||||
friend class C4AulDebug;
|
||||
public:
|
||||
C4AulScript(); // constructor
|
||||
virtual ~C4AulScript(); // destructor
|
||||
|
@ -389,8 +386,8 @@ public:
|
|||
enum Strict Strict; // new or even newer syntax?
|
||||
bool Temporary; // set for DirectExec-scripts; do not parse those
|
||||
|
||||
const char *GetScript() const { return Script.getData(); }
|
||||
virtual C4PropList * GetPropList() { return 0; }
|
||||
virtual C4ScriptHost * GetScriptHost() { return 0; }
|
||||
C4AulFunc *GetFuncRecursive(const char *pIdtf); // search function by identifier, including global funcs
|
||||
C4AulScriptFunc *GetSFunc(const char *pIdtf, C4AulAccess AccNeeded, bool fFailSafe = false); // get local sfunc, check access, check '~'-safety
|
||||
C4AulScriptFunc *GetSFunc(const char *pIdtf); // get local script function by name
|
||||
|
@ -412,6 +409,8 @@ public:
|
|||
friend class C4AulScriptFunc;
|
||||
friend class C4AulScriptEngine;
|
||||
friend class C4AulParseState;
|
||||
friend class C4AulDebug;
|
||||
friend class C4ScriptHost;
|
||||
|
||||
// Translate a string using the script's lang table
|
||||
std::string Translate(const std::string &text) const;
|
||||
|
@ -423,12 +422,7 @@ protected:
|
|||
C4AulScriptEngine *Engine; //owning engine
|
||||
C4AulScript *Owner, *Prev, *Next, *Child0, *ChildL; // tree structure
|
||||
|
||||
StdStrBuf Script; // script
|
||||
std::vector<C4AulBCC> Code;
|
||||
std::vector<const char *> PosForCode;
|
||||
C4AulBCC * LastCode;
|
||||
C4AulScriptState State; // script state
|
||||
bool Preparsing; // set while preparse
|
||||
bool Resolving; // set while include-resolving, to catch circular includes
|
||||
|
||||
std::list<C4ID> Includes; // include list
|
||||
|
@ -438,27 +432,16 @@ protected:
|
|||
C4AulFunc *GetOverloadedFunc(C4AulFunc *ByFunc);
|
||||
C4AulFunc *GetFunc(const char *pIdtf); // get local function by name
|
||||
|
||||
void AddBCC(C4AulBCCType eType, intptr_t = 0, const char * SPos = 0); // add byte code chunk and advance
|
||||
void RemoveLastBCC();
|
||||
void ClearCode();
|
||||
bool Preparse(); // preparse script; return if successfull
|
||||
void ParseFn(C4AulScriptFunc *Fn, bool fExprOnly = false, C4AulScriptContext* context = NULL); // parse single script function
|
||||
|
||||
bool Parse(); // parse preparsed script; return if successfull
|
||||
|
||||
bool ResolveIncludes(C4DefList *rDefs); // resolve includes
|
||||
bool ResolveAppends(C4DefList *rDefs); // resolve appends
|
||||
bool IncludesResolved;
|
||||
void AppendTo(C4AulScript &Scr, bool bHighPrio); // append to given script
|
||||
void UnLink(); // reset to unlinked state
|
||||
virtual void UnLink(); // reset to unlinked state
|
||||
virtual void AfterLink(); // called after linking is completed; presearch common funcs here
|
||||
virtual bool ReloadScript(const char *szPath, const char *szLanguage); // reload given script
|
||||
virtual bool Parse();
|
||||
|
||||
C4AulScript *FindFirstNonStrictScript(); // find first script that is not #strict
|
||||
|
||||
int GetCodePos() const { return Code.size(); }
|
||||
C4AulBCC *GetCodeByPos(int iPos) { return &Code[iPos]; }
|
||||
C4AulBCC *GetLastCode() { return LastCode; }
|
||||
};
|
||||
|
||||
// holds all C4AulScripts
|
||||
|
|
|
@ -267,17 +267,18 @@ void C4AulDebug::ProcessLine(const StdStrBuf &Line)
|
|||
break;
|
||||
}
|
||||
|
||||
if (script)
|
||||
if (script && script->GetScriptHost())
|
||||
{
|
||||
C4AulBCC* foundDebugChunk = NULL;
|
||||
const char* scriptText = script->GetScript();
|
||||
for (C4AulBCC* chunk = &script->Code[0]; chunk; chunk++)
|
||||
C4ScriptHost * sh = script->GetScriptHost();
|
||||
const char* scriptText = sh->GetScript();
|
||||
for (C4AulBCC* chunk = &sh->Code[0]; chunk; chunk++)
|
||||
{
|
||||
switch (chunk->bccType)
|
||||
{
|
||||
case AB_DEBUG:
|
||||
{
|
||||
int lineOfThisOne = SGetLine(scriptText, script->PosForCode[chunk - &script->Code[0]]);
|
||||
int lineOfThisOne = SGetLine(scriptText, sh->PosForCode[chunk - &sh->Code[0]]);
|
||||
if (lineOfThisOne == line)
|
||||
{
|
||||
foundDebugChunk = chunk;
|
||||
|
|
|
@ -1084,10 +1084,10 @@ C4Value C4AulDefFunc::Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPass
|
|||
}
|
||||
|
||||
|
||||
class C4DirectExecScript: public C4AulScript
|
||||
class C4DirectExecScript: public C4ScriptHost
|
||||
{
|
||||
public:
|
||||
C4DirectExecScript(C4AulScript * a, C4Object * pObj, const char *szContext): p(NULL)
|
||||
C4DirectExecScript(C4AulScript * a, C4Object * pObj, const char *szContext, C4LangStringTable * stringTable): p(NULL)
|
||||
{
|
||||
ScriptName = FormatString("%s in %s", szContext, a->ScriptName.getData());
|
||||
Strict = a->Strict;
|
||||
|
@ -1100,6 +1100,7 @@ public:
|
|||
}
|
||||
// FIXME: calls from definitions
|
||||
ClearCode();
|
||||
this->stringTable = stringTable;
|
||||
}
|
||||
virtual C4PropList * GetPropList() { return p; }
|
||||
C4PropList * p;
|
||||
|
@ -1115,8 +1116,7 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
|
|||
// profiler
|
||||
AulExec.StartDirectExec();
|
||||
// Create a new temporary script as child of this script
|
||||
C4AulScript* pScript = new C4DirectExecScript(this, pObj, szContext);
|
||||
pScript->stringTable = stringTable;
|
||||
C4ScriptHost* pScript = new C4DirectExecScript(this, pObj, szContext, stringTable);
|
||||
pScript->Reg2List(Engine, this);
|
||||
// Add a new function
|
||||
C4AulScriptFunc *pFunc = new C4AulScriptFunc(pScript, 0);
|
||||
|
@ -1125,7 +1125,8 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
|
|||
// Parse function
|
||||
try
|
||||
{
|
||||
pScript->ParseFn(pFunc, true, context);
|
||||
assert(pFunc->GetCodeOwner() == pScript);
|
||||
pFunc->ParseFn(true, context);
|
||||
}
|
||||
catch (C4AulError *ex)
|
||||
{
|
||||
|
@ -1135,7 +1136,6 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
|
|||
delete pScript;
|
||||
return C4VNull;
|
||||
}
|
||||
pFunc->CodePos = 1;
|
||||
pScript->State = ASS_PARSED;
|
||||
// Execute. The TemporaryScript-parameter makes sure the script will be deleted later on.
|
||||
C4Value vRetVal(AulExec.Exec(pFunc, pObj, NULL, fPassErrors, true));
|
||||
|
|
|
@ -161,9 +161,6 @@ void C4AulScript::UnLink()
|
|||
// do not unlink temporary (e.g., DirectExec-script in ReloadDef)
|
||||
if (Temporary) return;
|
||||
|
||||
// check if byte code needs to be freed
|
||||
ClearCode();
|
||||
|
||||
if (GetPropList()) GetPropList()->C4PropList::Clear();
|
||||
|
||||
// delete included/appended functions
|
||||
|
@ -181,10 +178,10 @@ void C4AulScript::UnLink()
|
|||
|
||||
pFunc = pNextFunc;
|
||||
}
|
||||
|
||||
// includes will have to be re-resolved now
|
||||
IncludesResolved = false;
|
||||
|
||||
|
||||
if (State > ASS_PREPARSED) State = ASS_PREPARSED;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ class C4AulParseState
|
|||
{
|
||||
public:
|
||||
enum Type { PARSER, PREPARSER };
|
||||
C4AulParseState(C4AulScriptFunc *Fn, C4AulScript * a, enum Type Type):
|
||||
C4AulParseState(C4AulScriptFunc *Fn, C4ScriptHost * a, enum Type Type):
|
||||
Fn(Fn), a(a), SPos(Fn ? Fn->Script : a->Script.getData()),
|
||||
TokenType(ATT_INVALID),
|
||||
Done(false),
|
||||
|
@ -138,7 +138,7 @@ public:
|
|||
{ }
|
||||
~C4AulParseState()
|
||||
{ while (pLoopStack) PopLoop(); ClearToken(); }
|
||||
C4AulScriptFunc *Fn; C4AulScript * a;
|
||||
C4AulScriptFunc *Fn; C4ScriptHost * a;
|
||||
const char *SPos; // current position in the script
|
||||
char Idtf[C4AUL_MAX_Identifier]; // current identifier
|
||||
C4AulTokenType TokenType; // current token type
|
||||
|
@ -271,8 +271,8 @@ C4AulParseError::C4AulParseError(C4AulParseState * state, const char *pMsg, cons
|
|||
if (state->Fn->pOrgScript && state->SPos)
|
||||
sMessage.AppendFormat(", %s:%d:%d)",
|
||||
state->Fn->pOrgScript->ScriptName.getData(),
|
||||
SGetLine(state->Fn->pOrgScript->Script.getData(), state->SPos),
|
||||
SLineGetCharacters(state->Fn->pOrgScript->Script.getData(), state->SPos));
|
||||
SGetLine(state->Fn->pOrgScript->GetScript(), state->SPos),
|
||||
SLineGetCharacters(state->Fn->pOrgScript->GetScript(), state->SPos));
|
||||
else
|
||||
sMessage.AppendChar(')');
|
||||
}
|
||||
|
@ -281,8 +281,8 @@ C4AulParseError::C4AulParseError(C4AulParseState * state, const char *pMsg, cons
|
|||
// Script name
|
||||
sMessage.AppendFormat(" (%s:%d:%d)",
|
||||
state->a->ScriptName.getData(),
|
||||
SGetLine(state->a->Script.getData(), state->SPos),
|
||||
SLineGetCharacters(state->a->Script.getData(), state->SPos));
|
||||
SGetLine(state->a->GetScript(), state->SPos),
|
||||
SLineGetCharacters(state->a->GetScript(), state->SPos));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -749,7 +749,7 @@ static const char * GetTTName(C4AulBCCType e)
|
|||
}
|
||||
}
|
||||
|
||||
void C4AulScript::AddBCC(C4AulBCCType eType, intptr_t X, const char * SPos)
|
||||
void C4ScriptHost::AddBCC(C4AulBCCType eType, intptr_t X, const char * SPos)
|
||||
{
|
||||
// store chunk
|
||||
C4AulBCC bcc;
|
||||
|
@ -769,7 +769,7 @@ void C4AulScript::AddBCC(C4AulBCCType eType, intptr_t X, const char * SPos)
|
|||
}
|
||||
}
|
||||
|
||||
void C4AulScript::RemoveLastBCC()
|
||||
void C4ScriptHost::RemoveLastBCC()
|
||||
{
|
||||
C4AulBCC *pBCC = &Code.back();
|
||||
switch (pBCC->bccType)
|
||||
|
@ -787,7 +787,7 @@ void C4AulScript::RemoveLastBCC()
|
|||
LastCode = NULL;
|
||||
}
|
||||
|
||||
void C4AulScript::ClearCode()
|
||||
void C4ScriptHost::ClearCode()
|
||||
{
|
||||
while(Code.size() > 0)
|
||||
RemoveLastBCC();
|
||||
|
@ -805,12 +805,19 @@ C4AulBCC * C4AulScriptFunc::GetCode()
|
|||
return &GetCodeOwner()->Code[CodePos];
|
||||
}
|
||||
|
||||
C4AulScript * C4AulScriptFunc::GetCodeOwner()
|
||||
C4ScriptHost * C4AulScriptFunc::GetCodeOwner()
|
||||
{
|
||||
return Owner == Owner->Engine ? LinkedTo->Owner : Owner;
|
||||
if (Owner == Owner->Engine)
|
||||
{
|
||||
return LinkedTo->Owner->GetScriptHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Owner->GetScriptHost();
|
||||
}
|
||||
}
|
||||
|
||||
bool C4AulScript::Preparse()
|
||||
bool C4ScriptHost::Preparse()
|
||||
{
|
||||
// handle easiest case first
|
||||
if (State < ASS_NONE) return false;
|
||||
|
@ -825,7 +832,7 @@ bool C4AulScript::Preparse()
|
|||
// belongs to this script?
|
||||
if (Func0->SFunc())
|
||||
if (Func0->SFunc()->pOrgScript == this)
|
||||
// then desroy linked funcs, too
|
||||
// then destroy linked funcs, too
|
||||
Func0->DestroyLinked();
|
||||
// destroy func
|
||||
delete Func0;
|
||||
|
@ -840,9 +847,6 @@ bool C4AulScript::Preparse()
|
|||
Engine->nonStrictCnt++;
|
||||
}
|
||||
|
||||
// done, reset state var
|
||||
Preparsing=false;
|
||||
|
||||
// #include will have to be resolved now...
|
||||
IncludesResolved = false;
|
||||
|
||||
|
@ -1259,20 +1263,19 @@ void C4AulParseState::UnexpectedToken(const char * Expected)
|
|||
throw new C4AulParseError(this, FormatString("%s expected, but found %s", Expected, GetTokenName(TokenType)).getData());
|
||||
}
|
||||
|
||||
void C4AulScript::ParseFn(C4AulScriptFunc *Fn, bool fExprOnly, C4AulScriptContext* context)
|
||||
void C4AulScriptFunc::ParseFn(bool fExprOnly, C4AulScriptContext* context)
|
||||
{
|
||||
// check if fn overloads other fn (all func tables are built now)
|
||||
// *MUST* check Fn->Owner-list, because it may be the engine (due to linked globals)
|
||||
if ((Fn->OwnerOverloaded = Fn->Owner->GetOverloadedFunc(Fn)))
|
||||
if (Fn->Owner == Fn->OwnerOverloaded->Owner)
|
||||
Fn->OwnerOverloaded->OverloadedBy=Fn;
|
||||
if ((OwnerOverloaded = Owner->GetOverloadedFunc(this)))
|
||||
if (Owner == OwnerOverloaded->Owner)
|
||||
OwnerOverloaded->OverloadedBy=this;
|
||||
// store byte code pos
|
||||
// (relative position to code start; code pointer may change while
|
||||
// parsing)
|
||||
assert(Fn->GetCodeOwner() == this);
|
||||
Fn->CodePos = Code.size();
|
||||
CodePos = GetCodeOwner()->Code.size();
|
||||
// parse
|
||||
C4AulParseState state(Fn, this, C4AulParseState::PARSER);
|
||||
C4AulParseState state(this, GetCodeOwner(), C4AulParseState::PARSER);
|
||||
state.ContextToExecIn = context;
|
||||
// get first token
|
||||
state.Shift();
|
||||
|
@ -1281,7 +1284,7 @@ void C4AulScript::ParseFn(C4AulScriptFunc *Fn, bool fExprOnly, C4AulScriptContex
|
|||
else
|
||||
{
|
||||
state.Parse_Expression();
|
||||
AddBCC(AB_RETURN, 0, state.SPos);
|
||||
GetCodeOwner()->AddBCC(AB_RETURN, 0, state.SPos);
|
||||
}
|
||||
// done
|
||||
return;
|
||||
|
@ -2927,17 +2930,22 @@ void C4AulParseState::Parse_Const()
|
|||
|
||||
bool C4AulScript::Parse()
|
||||
{
|
||||
// parse children
|
||||
C4AulScript *s = Child0;
|
||||
while (s) { s->Parse(); s = s->Next; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4ScriptHost::Parse()
|
||||
{
|
||||
C4AulScript::Parse();
|
||||
if (DEBUG_BYTECODE_DUMP)
|
||||
{
|
||||
fprintf(stderr, "parsing %s...\n", ScriptName.getData());
|
||||
}
|
||||
// parse children
|
||||
C4AulScript *s = Child0;
|
||||
while (s) { s->Parse(); s = s->Next; }
|
||||
// check state
|
||||
if (State != ASS_LINKED) return false;
|
||||
// don't parse global funcs again, as they're parsed already through links
|
||||
if (this == Engine) return false;
|
||||
|
||||
// delete existing code
|
||||
ClearCode();
|
||||
|
||||
|
@ -2958,7 +2966,8 @@ bool C4AulScript::Parse()
|
|||
// parse function
|
||||
try
|
||||
{
|
||||
ParseFn(Fn);
|
||||
assert(Fn->GetCodeOwner() == this);
|
||||
Fn->ParseFn();
|
||||
}
|
||||
catch (C4AulError *err)
|
||||
{
|
||||
|
@ -3074,7 +3083,7 @@ bool C4AulScript::Parse()
|
|||
C4AulScript *C4AulScript::FindFirstNonStrictScript()
|
||||
{
|
||||
// self is not #strict?
|
||||
if (Script && Strict < MAXSTRICT) return this;
|
||||
if (Strict < MAXSTRICT) return this;
|
||||
// search children
|
||||
C4AulScript *pNonStrScr;
|
||||
for (C4AulScript *pScr=Child0; pScr; pScr=pScr->Next)
|
||||
|
|
|
@ -35,13 +35,21 @@
|
|||
|
||||
/*--- C4ScriptHost ---*/
|
||||
|
||||
C4ScriptHost::C4ScriptHost() { }
|
||||
C4ScriptHost::C4ScriptHost()
|
||||
{
|
||||
Script = NULL;
|
||||
Code.clear();
|
||||
LastCode = NULL;
|
||||
stringTable = 0;
|
||||
}
|
||||
C4ScriptHost::~C4ScriptHost() { Clear(); }
|
||||
|
||||
void C4ScriptHost::Clear()
|
||||
{
|
||||
C4AulScript::Clear();
|
||||
ComponentHost.Clear();
|
||||
Script.Clear();
|
||||
ClearCode();
|
||||
}
|
||||
|
||||
bool C4ScriptHost::Load(C4Group &hGroup, const char *szFilename,
|
||||
|
|
|
@ -38,11 +38,31 @@ public:
|
|||
void Clear();
|
||||
bool Load(C4Group &hGroup, const char *szFilename,
|
||||
const char *szLanguage, C4LangStringTable *pLocalTable);
|
||||
const char *GetScript() const { return Script.getData(); }
|
||||
virtual C4ScriptHost * GetScriptHost() { return this; }
|
||||
protected:
|
||||
void SetError(const char *szMessage);
|
||||
void MakeScript();
|
||||
bool ReloadScript(const char *szPath, const char *szLanguage);
|
||||
C4ComponentHost ComponentHost;
|
||||
|
||||
|
||||
void AddBCC(C4AulBCCType eType, intptr_t = 0, const char * SPos = 0); // add byte code chunk and advance
|
||||
void RemoveLastBCC();
|
||||
void ClearCode();
|
||||
bool Preparse(); // preparse script; return if successfull
|
||||
bool Parse(); // parse preparsed script; return if successfull
|
||||
int GetCodePos() const { return Code.size(); }
|
||||
C4AulBCC *GetCodeByPos(int iPos) { return &Code[iPos]; }
|
||||
C4AulBCC *GetLastCode() { return LastCode; }
|
||||
|
||||
StdStrBuf Script; // script
|
||||
std::vector<C4AulBCC> Code;
|
||||
std::vector<const char *> PosForCode;
|
||||
C4AulBCC * LastCode;
|
||||
friend class C4AulParseState;
|
||||
friend class C4AulScriptFunc;
|
||||
friend class C4AulDebug;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue