Move Parser from C4AulScript to C4ScriptHost

Günther Brammer 2011-10-13 18:01:02 +02:00
parent 843642271d
commit f166fdaed7
9 changed files with 93 additions and 82 deletions

View File

@ -110,6 +110,7 @@ class C4RegionList;
class C4RoundResult;
class C4RoundResults;
class C4Scenario;
class C4ScriptHost;
class C4SoundSystem;
class C4Stream;
class C4String;

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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;
}

View File

@ -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)

View File

@ -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,

View File

@ -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;
};