From f166fdaed741148d913d7a05f2d5a283966d8f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Brammer?= Date: Thu, 13 Oct 2011 18:01:02 +0200 Subject: [PATCH] Move Parser from C4AulScript to C4ScriptHost --- src/C4Prototypes.h | 1 + src/script/C4Aul.cpp | 10 +----- src/script/C4Aul.h | 37 ++++++------------- src/script/C4AulDebug.cpp | 9 ++--- src/script/C4AulExec.cpp | 12 +++---- src/script/C4AulLink.cpp | 5 +-- src/script/C4AulParse.cpp | 71 +++++++++++++++++++++---------------- src/script/C4ScriptHost.cpp | 10 +++++- src/script/C4ScriptHost.h | 20 +++++++++++ 9 files changed, 93 insertions(+), 82 deletions(-) diff --git a/src/C4Prototypes.h b/src/C4Prototypes.h index 5508652ff..d879cdc02 100644 --- a/src/C4Prototypes.h +++ b/src/C4Prototypes.h @@ -110,6 +110,7 @@ class C4RegionList; class C4RoundResult; class C4RoundResults; class C4Scenario; +class C4ScriptHost; class C4SoundSystem; class C4Stream; class C4String; diff --git a/src/script/C4Aul.cpp b/src/script/C4Aul.cpp index 51d7b50a4..1c2dcbb28 100644 --- a/src/script/C4Aul.cpp +++ b/src/script/C4Aul.cpp @@ -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; } diff --git a/src/script/C4Aul.h b/src/script/C4Aul.h index 38035fcfa..76bf0fe84 100644 --- a/src/script/C4Aul.h +++ b/src/script/C4Aul.h @@ -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 Code; - std::vector PosForCode; - C4AulBCC * LastCode; C4AulScriptState State; // script state - bool Preparsing; // set while preparse bool Resolving; // set while include-resolving, to catch circular includes std::list 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 diff --git a/src/script/C4AulDebug.cpp b/src/script/C4AulDebug.cpp index 79822b678..bee3ff737 100644 --- a/src/script/C4AulDebug.cpp +++ b/src/script/C4AulDebug.cpp @@ -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; diff --git a/src/script/C4AulExec.cpp b/src/script/C4AulExec.cpp index 71956a8c1..35b1fe84e 100644 --- a/src/script/C4AulExec.cpp +++ b/src/script/C4AulExec.cpp @@ -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)); diff --git a/src/script/C4AulLink.cpp b/src/script/C4AulLink.cpp index 83eed784f..4b7596cf9 100644 --- a/src/script/C4AulLink.cpp +++ b/src/script/C4AulLink.cpp @@ -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; } diff --git a/src/script/C4AulParse.cpp b/src/script/C4AulParse.cpp index 319ff0dfa..a2b2e1474 100644 --- a/src/script/C4AulParse.cpp +++ b/src/script/C4AulParse.cpp @@ -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) diff --git a/src/script/C4ScriptHost.cpp b/src/script/C4ScriptHost.cpp index 50b511a2e..c69209550 100644 --- a/src/script/C4ScriptHost.cpp +++ b/src/script/C4ScriptHost.cpp @@ -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, diff --git a/src/script/C4ScriptHost.h b/src/script/C4ScriptHost.h index bf9d8d0a5..fccb9c17b 100644 --- a/src/script/C4ScriptHost.h +++ b/src/script/C4ScriptHost.h @@ -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 Code; + std::vector PosForCode; + C4AulBCC * LastCode; + friend class C4AulParseState; + friend class C4AulScriptFunc; + friend class C4AulDebug; };