forked from Mirrors/openclonk
DirectExec and C4ControlScript support executing script expressions that access variables and parameters of the parent context (used for watch expressions while debugging)
parent
99cbfecdff
commit
4902679b56
|
@ -49,6 +49,8 @@
|
|||
#include <C4AulDebug.h>
|
||||
#endif
|
||||
|
||||
#include <C4AulExec.h>
|
||||
|
||||
// *** C4ControlPacket
|
||||
C4ControlPacket::C4ControlPacket()
|
||||
: iByClient(::Control.ClientID())
|
||||
|
@ -288,7 +290,7 @@ void C4ControlScript::Execute() const
|
|||
else
|
||||
// default: Fallback to global context
|
||||
pScript = &::ScriptEngine;
|
||||
C4Value rVal(pScript->DirectExec(pObj, szScript, "console script"));
|
||||
C4Value rVal(pScript->DirectExec(pObj, szScript, "console script", false, C4AulScript::MAXSTRICT, fUseVarsFromCallerContext ? AulExec.GetContext(AulExec.GetContextDepth()-1) : NULL));
|
||||
#ifndef NOAULDEBUG
|
||||
C4AulDebug* pDebug;
|
||||
if (pDebug = ::ScriptEngine.GetDebugger())
|
||||
|
@ -324,6 +326,7 @@ void C4ControlScript::CompileFunc(StdCompiler *pComp)
|
|||
{
|
||||
pComp->Value(mkNamingAdapt(iTargetObj, "TargetObj", -1));
|
||||
pComp->Value(mkNamingAdapt(fInternal, "Internal", false));
|
||||
pComp->Value(mkNamingAdapt(fUseVarsFromCallerContext, "UseVarsFromCallerContext", false));
|
||||
pComp->Value(mkNamingAdapt(Script, "Script", ""));
|
||||
C4ControlPacket::CompileFunc(pComp);
|
||||
}
|
||||
|
|
|
@ -140,12 +140,13 @@ public:
|
|||
C4ControlScript()
|
||||
: iTargetObj(-1), fInternal(true)
|
||||
{ }
|
||||
C4ControlScript(const char *szScript, int32_t iTargetObj = SCOPE_Global, bool fInternal = true)
|
||||
: iTargetObj(iTargetObj), fInternal(fInternal), Script(szScript, true)
|
||||
C4ControlScript(const char *szScript, int32_t iTargetObj = SCOPE_Global, bool fInternal = true, bool fUseVarsFromCallerContext = false)
|
||||
: iTargetObj(iTargetObj), fInternal(fInternal), Script(szScript, true), fUseVarsFromCallerContext(fUseVarsFromCallerContext)
|
||||
{ }
|
||||
protected:
|
||||
int32_t iTargetObj;
|
||||
bool fInternal; // silent execute
|
||||
bool fUseVarsFromCallerContext;
|
||||
StdStrBuf Script;
|
||||
public:
|
||||
void SetTargetObj(int32_t iObj) { iTargetObj = iObj; }
|
||||
|
|
|
@ -145,6 +145,9 @@ enum C4AulBCCType
|
|||
AB_PAR_V,
|
||||
AB_FUNC, // function
|
||||
|
||||
AB_PARN_CONTEXT,
|
||||
AB_VARN_CONTEXT,
|
||||
|
||||
// prefix
|
||||
AB_Inc1, // ++
|
||||
AB_Dec1, // --
|
||||
|
@ -472,7 +475,7 @@ protected:
|
|||
void AddBCC(C4AulBCCType eType, intptr_t = 0, const char * SPos = 0); // add byte code chunk and advance
|
||||
void ClearCode();
|
||||
bool Preparse(); // preparse script; return if successfull
|
||||
void ParseFn(C4AulScriptFunc *Fn, bool fExprOnly = false); // parse single script function
|
||||
void ParseFn(C4AulScriptFunc *Fn, bool fExprOnly = false, C4AulScriptContext* context = NULL); // parse single script function
|
||||
|
||||
bool Parse(); // parse preparsed script; return if successfull
|
||||
void ParseDescs(); // parse function descs
|
||||
|
@ -509,7 +512,7 @@ public:
|
|||
void AddFunc(const char *pIdtf, C4ScriptFnDef* Def); // add def def func to table
|
||||
|
||||
public:
|
||||
C4Value DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors = false, enum Strict Strict = MAXSTRICT); // directly parse uncompiled script (WARG! CYCLES!)
|
||||
C4Value DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors = false, enum Strict Strict = MAXSTRICT, C4AulScriptContext* context = NULL); // directly parse uncompiled script (WARG! CYCLES!)
|
||||
void ResetProfilerTimes(); // zero all profiler times of owned functions
|
||||
void CollectProfilerTimes(class C4AulProfiler &rProfiler);
|
||||
|
||||
|
|
|
@ -201,6 +201,14 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
case AB_PARN_V:
|
||||
PushValue(pCurCtx->Pars[pCPos->Par.i]);
|
||||
break;
|
||||
|
||||
case AB_PARN_CONTEXT:
|
||||
PushValueRef(AulExec.GetContext(AulExec.GetContextDepth()-2)->Pars[pCPos->Par.i]);
|
||||
break;
|
||||
|
||||
case AB_VARN_CONTEXT:
|
||||
PushValueRef(AulExec.GetContext(AulExec.GetContextDepth()-2)->Vars[pCPos->Par.i]);
|
||||
break;
|
||||
|
||||
case AB_VARN_R:
|
||||
PushValueRef(pCurCtx->Vars[pCPos->Par.i]);
|
||||
|
@ -1206,7 +1214,7 @@ C4Value C4AulDefFunc::Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPass
|
|||
|
||||
}
|
||||
|
||||
C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors, enum Strict Strict)
|
||||
C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors, enum Strict Strict, C4AulScriptContext* context)
|
||||
{
|
||||
#ifdef DEBUGREC_SCRIPT
|
||||
AddDbgRec(RCT_DirectExec, szScript, strlen(szScript)+1);
|
||||
|
@ -1240,7 +1248,7 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char
|
|||
// Parse function
|
||||
try
|
||||
{
|
||||
pScript->ParseFn(pFunc, true);
|
||||
pScript->ParseFn(pFunc, true, context);
|
||||
}
|
||||
catch (C4AulError *ex)
|
||||
{
|
||||
|
|
|
@ -131,7 +131,8 @@ public:
|
|||
Type(Type),
|
||||
fJump(false),
|
||||
iStack(0),
|
||||
pLoopStack(NULL)
|
||||
pLoopStack(NULL),
|
||||
ContextToExecIn(NULL)
|
||||
{ }
|
||||
~C4AulParseState()
|
||||
{ while (pLoopStack) PopLoop(); ClearToken(); }
|
||||
|
@ -142,6 +143,7 @@ public:
|
|||
long cInt; // current int constant (long for compatibility with x86_64)
|
||||
bool Done; // done parsing?
|
||||
enum Type Type; // emitting bytecode?
|
||||
C4AulScriptContext* ContextToExecIn;
|
||||
void Parse_Script();
|
||||
void Parse_FuncHead();
|
||||
void Parse_Desc();
|
||||
|
@ -846,6 +848,9 @@ static const char * GetTTName(C4AulBCCType e)
|
|||
case AB_PAR_V: return "PAR_V";
|
||||
case AB_FUNC: return "FUNC"; // function
|
||||
|
||||
case AB_PARN_CONTEXT: return "AB_PARN_CONTEXT";
|
||||
case AB_VARN_CONTEXT: return "AB_VARN_CONTEXT";
|
||||
|
||||
// prefix
|
||||
case AB_Inc1: return "Inc1"; // ++
|
||||
case AB_Dec1: return "Dec1"; // --
|
||||
|
@ -1028,6 +1033,8 @@ void C4AulParseState::AddBCC(C4AulBCCType eType, intptr_t X)
|
|||
case AB_LOCALN_V:
|
||||
case AB_GLOBALN_R:
|
||||
case AB_GLOBALN_V:
|
||||
case AB_PARN_CONTEXT:
|
||||
case AB_VARN_CONTEXT:
|
||||
iStack++;
|
||||
break;
|
||||
|
||||
|
@ -1290,7 +1297,7 @@ 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)
|
||||
void C4AulScript::ParseFn(C4AulScriptFunc *Fn, 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)
|
||||
|
@ -1303,6 +1310,7 @@ void C4AulScript::ParseFn(C4AulScriptFunc *Fn, bool fExprOnly)
|
|||
Fn->Code = (C4AulBCC *) (CPos - Code);
|
||||
// parse
|
||||
C4AulParseState state(Fn, this, C4AulParseState::PARSER);
|
||||
state.ContextToExecIn = context;
|
||||
// get first token
|
||||
state.Shift();
|
||||
if (!fExprOnly)
|
||||
|
@ -2299,6 +2307,7 @@ void C4AulParseState::Parse_ForEach()
|
|||
|
||||
void C4AulParseState::Parse_Expression(int iParentPrio)
|
||||
{
|
||||
int ndx;
|
||||
switch (TokenType)
|
||||
{
|
||||
case ATT_IDTF:
|
||||
|
@ -2317,6 +2326,16 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
|
|||
AddBCC(AB_VARN_R, Fn->VarNamed.GetItemNr(Idtf));
|
||||
Shift();
|
||||
}
|
||||
else if (ContextToExecIn && (ndx = ContextToExecIn->Func->ParNamed.GetItemNr(Idtf)) != -1)
|
||||
{
|
||||
AddBCC(AB_PARN_CONTEXT, ndx);
|
||||
Shift();
|
||||
}
|
||||
else if (ContextToExecIn && (ndx = ContextToExecIn->Func->VarNamed.GetItemNr(Idtf)) != -1)
|
||||
{
|
||||
AddBCC(AB_VARN_CONTEXT, ndx);
|
||||
Shift();
|
||||
}
|
||||
// check for variable (local)
|
||||
else if (a->LocalNamed.GetItemNr(Idtf) != -1)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue