forked from Mirrors/openclonk
Move code generation into its own class
parent
b00b8554ab
commit
4092911349
|
@ -155,6 +155,7 @@ public:
|
|||
friend class C4AulProfiler;
|
||||
friend class C4ScriptHost;
|
||||
friend class C4AulParse;
|
||||
friend class C4CodeGen;
|
||||
friend class C4AulDebug;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "script/C4Aul.h"
|
||||
#include "script/C4AulDebug.h"
|
||||
#include "script/C4AulExec.h"
|
||||
#include "script/C4AulScriptFunc.h"
|
||||
#include "object/C4Def.h"
|
||||
#include "game/C4Game.h"
|
||||
#include "lib/C4Log.h"
|
||||
|
@ -120,10 +119,7 @@ C4AulParse::C4AulParse(C4ScriptHost *a, enum Type Type) :
|
|||
SPos(a->Script.getData()), TokenSPos(SPos),
|
||||
TokenType(ATT_INVALID),
|
||||
Type(Type),
|
||||
ContextToExecIn(NULL),
|
||||
fJump(false),
|
||||
iStack(0),
|
||||
pLoopStack(NULL)
|
||||
ContextToExecIn(NULL)
|
||||
{ }
|
||||
|
||||
C4AulParse::C4AulParse(C4AulScriptFunc * Fn, C4AulScriptContext* context, C4AulScriptEngine *Engine) :
|
||||
|
@ -131,15 +127,11 @@ C4AulParse::C4AulParse(C4AulScriptFunc * Fn, C4AulScriptContext* context, C4AulS
|
|||
SPos(Fn->Script), TokenSPos(SPos),
|
||||
TokenType(ATT_INVALID),
|
||||
Type(C4AulParse::PARSER),
|
||||
ContextToExecIn(context),
|
||||
fJump(false),
|
||||
iStack(0),
|
||||
pLoopStack(NULL)
|
||||
{ }
|
||||
ContextToExecIn(context)
|
||||
{ codegen.Fn = Fn; }
|
||||
|
||||
C4AulParse::~C4AulParse()
|
||||
{
|
||||
while (pLoopStack) PopLoop(0);
|
||||
ClearToken();
|
||||
}
|
||||
|
||||
|
@ -645,14 +637,14 @@ static const char * GetTTName(C4AulBCCType e)
|
|||
}
|
||||
}
|
||||
|
||||
void C4AulParse::DumpByteCode()
|
||||
void C4AulScriptFunc::DumpByteCode()
|
||||
{
|
||||
if (DEBUG_BYTECODE_DUMP && Type == PARSER)
|
||||
if (DEBUG_BYTECODE_DUMP)
|
||||
{
|
||||
fprintf(stderr, "%s:\n", Fn->GetName());
|
||||
fprintf(stderr, "%s:\n", GetName());
|
||||
std::map<C4AulBCC *, int> labels;
|
||||
int labeln = 0;
|
||||
for (C4AulBCC *pBCC = Fn->GetCode(); pBCC->bccType != AB_EOFN; pBCC++)
|
||||
for (C4AulBCC *pBCC = GetCode(); pBCC->bccType != AB_EOFN; pBCC++)
|
||||
{
|
||||
switch (pBCC->bccType)
|
||||
{
|
||||
|
@ -661,12 +653,12 @@ void C4AulParse::DumpByteCode()
|
|||
default: break;
|
||||
}
|
||||
}
|
||||
for (C4AulBCC *pBCC = Fn->GetCode();; pBCC++)
|
||||
for (C4AulBCC *pBCC = GetCode();; pBCC++)
|
||||
{
|
||||
C4AulBCCType eType = pBCC->bccType;
|
||||
if (labels.find(pBCC) != labels.end())
|
||||
fprintf(stderr, "%d:\n", labels[pBCC]);
|
||||
fprintf(stderr, "\t%d\t%s", Fn->GetLineOfCode(pBCC), GetTTName(eType));
|
||||
fprintf(stderr, "\t%d\t%s", GetLineOfCode(pBCC), GetTTName(eType));
|
||||
if (strlen(GetTTName(eType)) < 8) fprintf(stderr, " ");
|
||||
switch (eType)
|
||||
{
|
||||
|
@ -760,7 +752,7 @@ bool C4ScriptHost::Preparse()
|
|||
}
|
||||
|
||||
|
||||
int C4AulParse::GetStackValue(C4AulBCCType eType, intptr_t X)
|
||||
int C4CodeGen::GetStackValue(C4AulBCCType eType, intptr_t X)
|
||||
{
|
||||
switch (eType)
|
||||
{
|
||||
|
@ -860,10 +852,8 @@ void C4AulParse::DebugChunk()
|
|||
AddBCC(AB_DEBUG);
|
||||
}
|
||||
|
||||
int C4AulParse::AddBCC(C4AulBCCType eType, intptr_t X)
|
||||
int C4CodeGen::AddBCC(const char * TokenSPos, C4AulBCCType eType, intptr_t X)
|
||||
{
|
||||
if (Type != PARSER) return -1;
|
||||
|
||||
// Track stack size
|
||||
iStack += GetStackValue(eType, X);
|
||||
|
||||
|
@ -962,7 +952,7 @@ int C4AulParse::AddBCC(C4AulBCCType eType, intptr_t X)
|
|||
return Fn->GetCodePos() - 1;
|
||||
}
|
||||
|
||||
void C4AulParse::RemoveLastBCC()
|
||||
void C4CodeGen::RemoveLastBCC()
|
||||
{
|
||||
// Security: This is unsafe on anything that might get optimized away
|
||||
C4AulBCC *pBCC = Fn->GetLastCode();
|
||||
|
@ -973,7 +963,7 @@ void C4AulParse::RemoveLastBCC()
|
|||
Fn->RemoveLastBCC();
|
||||
}
|
||||
|
||||
C4V_Type C4AulParse::GetLastRetType(C4V_Type to)
|
||||
C4V_Type C4CodeGen::GetLastRetType(C4AulScriptEngine * Engine, C4V_Type to)
|
||||
{
|
||||
C4V_Type from;
|
||||
switch (Fn->GetLastCode()->bccType)
|
||||
|
@ -1026,9 +1016,8 @@ C4V_Type C4AulParse::GetLastRetType(C4V_Type to)
|
|||
return from;
|
||||
}
|
||||
|
||||
C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
|
||||
C4AulBCC C4CodeGen::MakeSetter(const char * SPos, bool fLeaveValue)
|
||||
{
|
||||
if(Type != PARSER) { return C4AulBCC(AB_ERR, 0); }
|
||||
C4AulBCC Value = *(Fn->GetLastCode()), Setter = Value;
|
||||
// Check type
|
||||
switch (Value.bccType)
|
||||
|
@ -1049,7 +1038,7 @@ C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
|
|||
break;
|
||||
case AB_GLOBALN: Setter.bccType = AB_GLOBALN_SET; break;
|
||||
default:
|
||||
throw C4AulParseError(this, "assignment to a constant");
|
||||
throw C4AulParseError(Fn, SPos, "assignment to a constant");
|
||||
}
|
||||
// If the new value is produced using the old one, the parameters to get the old one need to be duplicated.
|
||||
// Otherwise, the setter can just use the parameters originally meant for the getter.
|
||||
|
@ -1060,7 +1049,7 @@ C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
|
|||
// STACK_SET has a side effect, so it can't be simply removed.
|
||||
// Discard the unused value the usual way instead.
|
||||
if (!fLeaveValue)
|
||||
AddBCC(AB_STACK, -1);
|
||||
AddBCC(SPos, AB_STACK, -1);
|
||||
// The original parameter isn't needed anymore, since in contrast to the other getters
|
||||
// it does not indicate a position.
|
||||
iParCount = 0;
|
||||
|
@ -1073,9 +1062,9 @@ C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
|
|||
if (fLeaveValue && iParCount)
|
||||
{
|
||||
for(int i = 0; i < iParCount; i++)
|
||||
AddBCC(AB_DUP, 1 - iParCount);
|
||||
AddBCC(SPos, AB_DUP, 1 - iParCount);
|
||||
// Finally re-add original BCC
|
||||
AddBCC(Value.bccType, Value.Par.X);
|
||||
AddBCC(SPos, Value.bccType, Value.Par.X);
|
||||
}
|
||||
// Done. The returned BCC should be added later once the value to be set was pushed on top.
|
||||
assert(iParCount == -GetStackValue(Setter.bccType, Setter.Par.X));
|
||||
|
@ -1084,10 +1073,10 @@ C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
|
|||
|
||||
int C4AulParse::AddVarAccess(C4AulBCCType eType, intptr_t varnum)
|
||||
{
|
||||
return AddBCC(eType, 1 + varnum - (iStack + Fn->VarNamed.iSize));
|
||||
return AddBCC(eType, 1 + varnum - (codegen.iStack + Fn->VarNamed.iSize));
|
||||
}
|
||||
|
||||
int C4AulParse::JumpHere()
|
||||
int C4CodeGen::JumpHere()
|
||||
{
|
||||
// Set flag so the next generated code chunk won't get joined
|
||||
fJump = true;
|
||||
|
@ -1099,9 +1088,8 @@ static bool IsJump(C4AulBCCType t)
|
|||
return t == AB_JUMP || t == AB_JUMPAND || t == AB_JUMPOR || t == AB_JUMPNNIL || t == AB_CONDN || t == AB_COND;
|
||||
}
|
||||
|
||||
void C4AulParse::SetJumpHere(int iJumpOp)
|
||||
void C4CodeGen::SetJumpHere(int iJumpOp)
|
||||
{
|
||||
if (Type != PARSER) return;
|
||||
// Set target
|
||||
C4AulBCC *pBCC = Fn->GetCodeByPos(iJumpOp);
|
||||
assert(IsJump(pBCC->bccType));
|
||||
|
@ -1110,23 +1098,21 @@ void C4AulParse::SetJumpHere(int iJumpOp)
|
|||
fJump = true;
|
||||
}
|
||||
|
||||
void C4AulParse::SetJump(int iJumpOp, int iWhere)
|
||||
void C4CodeGen::SetJump(int iJumpOp, int iWhere)
|
||||
{
|
||||
if (Type != PARSER) return;
|
||||
// Set target
|
||||
C4AulBCC *pBCC = Fn->GetCodeByPos(iJumpOp);
|
||||
assert(IsJump(pBCC->bccType));
|
||||
pBCC->Par.i = iWhere - iJumpOp;
|
||||
}
|
||||
|
||||
void C4AulParse::AddJump(C4AulBCCType eType, int iWhere)
|
||||
void C4CodeGen::AddJump(const char * SPos, C4AulBCCType eType, int iWhere)
|
||||
{
|
||||
AddBCC(eType, iWhere - Fn->GetCodePos());
|
||||
AddBCC(SPos, eType, iWhere - Fn->GetCodePos());
|
||||
}
|
||||
|
||||
void C4AulParse::PushLoop()
|
||||
void C4CodeGen::PushLoop()
|
||||
{
|
||||
if (Type != PARSER) return;
|
||||
Loop *pNew = new Loop();
|
||||
pNew->StackSize = iStack;
|
||||
pNew->Controls = NULL;
|
||||
|
@ -1134,9 +1120,8 @@ void C4AulParse::PushLoop()
|
|||
pLoopStack = pNew;
|
||||
}
|
||||
|
||||
void C4AulParse::PopLoop(int ContinueJump)
|
||||
void C4CodeGen::PopLoop(int ContinueJump)
|
||||
{
|
||||
if (Type != PARSER) return;
|
||||
// Set targets for break/continue
|
||||
for (Loop::Control *pCtrl = pLoopStack->Controls; pCtrl; pCtrl = pCtrl->Next)
|
||||
if (pCtrl->Break)
|
||||
|
@ -1158,18 +1143,31 @@ void C4AulParse::PopLoop(int ContinueJump)
|
|||
delete pLoop;
|
||||
}
|
||||
|
||||
void C4AulParse::AddLoopControl(bool fBreak)
|
||||
void C4CodeGen::AddLoopControl(const char * SPos, bool fBreak)
|
||||
{
|
||||
if (Type != PARSER) return;
|
||||
// Insert code
|
||||
if (pLoopStack->StackSize != iStack)
|
||||
AddBCC(AB_STACK, pLoopStack->StackSize - iStack);
|
||||
AddBCC(SPos, AB_STACK, pLoopStack->StackSize - iStack);
|
||||
Loop::Control *pNew = new Loop::Control();
|
||||
pNew->Break = fBreak;
|
||||
pNew->Pos = Fn->GetCodePos();
|
||||
pNew->Next = pLoopStack->Controls;
|
||||
pLoopStack->Controls = pNew;
|
||||
AddBCC(AB_JUMP);
|
||||
AddBCC(SPos, AB_JUMP);
|
||||
}
|
||||
|
||||
void C4CodeGen::ErrorOut(const char * SPos)
|
||||
{
|
||||
// make all jumps that don't have their destination yet jump here
|
||||
for (unsigned int i = 0; i < Fn->Code.size(); i++)
|
||||
{
|
||||
C4AulBCC *pBCC = &Fn->Code[i];
|
||||
if (IsJump(pBCC->bccType))
|
||||
if (!pBCC->Par.i)
|
||||
pBCC->Par.i = Fn->Code.size() - i;
|
||||
}
|
||||
// add an error chunk
|
||||
AddBCC(SPos, AB_ERR);
|
||||
}
|
||||
|
||||
const char * C4AulParse::GetTokenName(C4AulTokenType TokenType)
|
||||
|
@ -1345,16 +1343,7 @@ void C4AulParse::Parse_Script(C4ScriptHost * scripthost)
|
|||
|
||||
if (Fn)
|
||||
{
|
||||
// make all jumps that don't have their destination yet jump here
|
||||
for (unsigned int i = 0; i < Fn->Code.size(); i++)
|
||||
{
|
||||
C4AulBCC *pBCC = &Fn->Code[i];
|
||||
if (IsJump(pBCC->bccType))
|
||||
if (!pBCC->Par.i)
|
||||
pBCC->Par.i = Fn->Code.size() - i;
|
||||
}
|
||||
// add an error chunk
|
||||
AddBCC(AB_ERR);
|
||||
codegen.ErrorOut(TokenSPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1425,6 +1414,7 @@ void C4AulParse::Parse_FuncBody()
|
|||
{
|
||||
// Parse function body
|
||||
assert(Fn);
|
||||
codegen.Fn = Fn;
|
||||
if (Type == PREPARSER)
|
||||
{
|
||||
// This might be a reload, clear all parameters and local vars
|
||||
|
@ -1493,21 +1483,21 @@ void C4AulParse::Parse_FuncBody()
|
|||
// Push variables
|
||||
if (Fn->VarNamed.iSize)
|
||||
AddBCC(AB_STACK, Fn->VarNamed.iSize);
|
||||
iStack = 0;
|
||||
codegen.iStack = 0;
|
||||
while (TokenType != ATT_BLCLOSE)
|
||||
{
|
||||
Parse_Statement();
|
||||
assert(!iStack);
|
||||
assert(!codegen.iStack);
|
||||
}
|
||||
// return nil if the function doesn't return anything
|
||||
C4AulBCC * CPos = Fn->GetLastCode();
|
||||
if (!CPos || CPos->bccType != AB_RETURN || fJump)
|
||||
if (!CPos || CPos->bccType != AB_RETURN || codegen.fJump)
|
||||
{
|
||||
AddBCC(AB_NIL);
|
||||
DebugChunk();
|
||||
AddBCC(AB_RETURN);
|
||||
}
|
||||
DumpByteCode();
|
||||
if (Type == PARSER) Fn->DumpByteCode();
|
||||
// add separator
|
||||
AddBCC(AB_EOFN);
|
||||
// Do not blame this function for script errors between functions
|
||||
|
@ -1638,13 +1628,13 @@ void C4AulParse::Parse_Statement()
|
|||
if (Type == PARSER)
|
||||
{
|
||||
// Must be inside a loop
|
||||
if (!pLoopStack)
|
||||
if (!codegen.pLoopStack)
|
||||
{
|
||||
Error("'break' is only allowed inside loops");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLoopControl(true);
|
||||
codegen.AddLoopControl(TokenSPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1654,13 +1644,13 @@ void C4AulParse::Parse_Statement()
|
|||
if (Type == PARSER)
|
||||
{
|
||||
// Must be inside a loop
|
||||
if (!pLoopStack)
|
||||
if (!codegen.pLoopStack)
|
||||
{
|
||||
Error("'continue' is only allowed inside loops");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLoopControl(false);
|
||||
codegen.AddLoopControl(TokenSPos, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1904,16 +1894,16 @@ void C4AulParse::Parse_DoWhile()
|
|||
{
|
||||
Shift();
|
||||
// Save position for later jump back
|
||||
int Start = JumpHere();
|
||||
int Start = codegen.JumpHere();
|
||||
// We got a loop
|
||||
PushLoop();
|
||||
// Execute body
|
||||
Parse_Statement();
|
||||
int BeforeCond = -1;
|
||||
if (Type == PARSER)
|
||||
for (Loop::Control *pCtrl2 = pLoopStack->Controls; pCtrl2; pCtrl2 = pCtrl2->Next)
|
||||
for (C4CodeGen::Loop::Control *pCtrl2 = codegen.pLoopStack->Controls; pCtrl2; pCtrl2 = pCtrl2->Next)
|
||||
if (!pCtrl2->Break)
|
||||
BeforeCond = JumpHere();
|
||||
BeforeCond = codegen.JumpHere();
|
||||
// Execute condition
|
||||
if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_While))
|
||||
UnexpectedToken("'while'");
|
||||
|
@ -1931,7 +1921,7 @@ void C4AulParse::Parse_While()
|
|||
{
|
||||
Shift();
|
||||
// Save position for later jump back
|
||||
int iStart = JumpHere();
|
||||
int iStart = codegen.JumpHere();
|
||||
// Execute condition
|
||||
Match(ATT_BOPEN);
|
||||
Parse_Expression();
|
||||
|
@ -1996,7 +1986,7 @@ void C4AulParse::Parse_For()
|
|||
if (TokenType != ATT_SCOLON)
|
||||
{
|
||||
// Add condition code
|
||||
iCondition = JumpHere();
|
||||
iCondition = codegen.JumpHere();
|
||||
Parse_Expression();
|
||||
// Jump out
|
||||
iJumpOut = AddBCC(AB_CONDN);
|
||||
|
@ -2010,7 +2000,7 @@ void C4AulParse::Parse_For()
|
|||
// Must jump over incrementor
|
||||
iJumpBody = AddBCC(AB_JUMP);
|
||||
// Add incrementor code
|
||||
iIncrementor = JumpHere();
|
||||
iIncrementor = codegen.JumpHere();
|
||||
Parse_Expression();
|
||||
AddBCC(AB_STACK, -1);
|
||||
// Jump to condition
|
||||
|
@ -2022,7 +2012,7 @@ void C4AulParse::Parse_For()
|
|||
// Allow break/continue from now on
|
||||
PushLoop();
|
||||
// Body
|
||||
int iBody = JumpHere();
|
||||
int iBody = codegen.JumpHere();
|
||||
if (iJumpBody != -1)
|
||||
SetJumpHere(iJumpBody);
|
||||
Parse_Statement();
|
||||
|
|
|
@ -18,10 +18,53 @@
|
|||
#define INC_C4AulParse
|
||||
|
||||
#include "script/C4Aul.h"
|
||||
#include "script/C4AulScriptFunc.h"
|
||||
|
||||
enum C4AulBCCType : int;
|
||||
enum C4AulTokenType : int;
|
||||
|
||||
class C4CodeGen
|
||||
{
|
||||
public:
|
||||
C4AulScriptFunc *Fn;
|
||||
bool fJump = false;
|
||||
int iStack = 0;
|
||||
|
||||
int GetStackValue(C4AulBCCType eType, intptr_t X = 0);
|
||||
int AddBCC(const char * SPos, C4AulBCCType eType, intptr_t X = 0);
|
||||
void ErrorOut(const char * SPos);
|
||||
void RemoveLastBCC();
|
||||
C4V_Type GetLastRetType(C4AulScriptEngine * Engine, C4V_Type to); // for warning purposes
|
||||
|
||||
C4AulBCC MakeSetter(const char * TokenSPos, bool fLeaveValue = false); // Prepares to generate a setter for the last value that was generated
|
||||
|
||||
int JumpHere(); // Get position for a later jump to next instruction added
|
||||
void SetJumpHere(int iJumpOp); // Use the next inserted instruction as jump target for the given jump operation
|
||||
void SetJump(int iJumpOp, int iWhere);
|
||||
void AddJump(const char * SPos, C4AulBCCType eType, int iWhere);
|
||||
|
||||
// Keep track of loops and break/continue usages
|
||||
struct Loop
|
||||
{
|
||||
struct Control
|
||||
{
|
||||
bool Break;
|
||||
int Pos;
|
||||
Control *Next;
|
||||
};
|
||||
Control *Controls;
|
||||
int StackSize;
|
||||
Loop *Next;
|
||||
};
|
||||
Loop *pLoopStack = NULL;
|
||||
|
||||
void PushLoop();
|
||||
void PopLoop(int ContinueJump);
|
||||
void AddLoopControl(const char * SPos, bool fBreak);
|
||||
~C4CodeGen()
|
||||
{ while (pLoopStack) PopLoop(0); }
|
||||
};
|
||||
|
||||
struct C4ScriptOpDef
|
||||
{
|
||||
unsigned short Priority;
|
||||
|
@ -94,42 +137,24 @@ private:
|
|||
void Error(const char *pMsg, ...) GNUC_FORMAT_ATTRIBUTE_O;
|
||||
void AppendPosition(StdStrBuf & Buf);
|
||||
|
||||
bool fJump;
|
||||
int iStack;
|
||||
|
||||
int GetStackValue(C4AulBCCType eType, intptr_t X = 0);
|
||||
int AddBCC(C4AulBCCType eType, intptr_t X = 0);
|
||||
int AddVarAccess(C4AulBCCType eType, intptr_t varnum);
|
||||
void DebugChunk();
|
||||
void RemoveLastBCC();
|
||||
C4V_Type GetLastRetType(C4V_Type to); // for warning purposes
|
||||
void DumpByteCode();
|
||||
C4CodeGen codegen;
|
||||
int AddBCC(C4AulBCCType eType, intptr_t X = 0)
|
||||
{ if (Type == PARSER) return codegen.AddBCC(TokenSPos, eType, X); else return -1; }
|
||||
C4V_Type GetLastRetType(C4V_Type to)
|
||||
{ return codegen.GetLastRetType(Engine, to); }
|
||||
C4AulBCC MakeSetter(bool fLeaveValue = false)
|
||||
{ return Type == PARSER ? codegen.MakeSetter(TokenSPos, fLeaveValue) : C4AulBCC(AB_ERR, 0); }
|
||||
void SetJumpHere(int iJumpOp)
|
||||
{ if (Type == PARSER) codegen.SetJumpHere(iJumpOp); }
|
||||
void AddJump(C4AulBCCType eType, int iWhere)
|
||||
{ if (Type == PARSER) codegen.AddJump(TokenSPos, eType, iWhere); }
|
||||
void PushLoop()
|
||||
{ if (Type == PARSER) codegen.PushLoop(); }
|
||||
void PopLoop(int Jump)
|
||||
{ if (Type == PARSER) codegen.PopLoop(Jump); }
|
||||
|
||||
C4AulBCC MakeSetter(bool fLeaveValue = false); // Prepares to generate a setter for the last value that was generated
|
||||
|
||||
int JumpHere(); // Get position for a later jump to next instruction added
|
||||
void SetJumpHere(int iJumpOp); // Use the next inserted instruction as jump target for the given jump operation
|
||||
void SetJump(int iJumpOp, int iWhere);
|
||||
void AddJump(C4AulBCCType eType, int iWhere);
|
||||
|
||||
// Keep track of loops and break/continue usages
|
||||
struct Loop
|
||||
{
|
||||
struct Control
|
||||
{
|
||||
bool Break;
|
||||
int Pos;
|
||||
Control *Next;
|
||||
};
|
||||
Control *Controls;
|
||||
int StackSize;
|
||||
Loop *Next;
|
||||
};
|
||||
Loop *pLoopStack;
|
||||
|
||||
void PushLoop();
|
||||
void PopLoop(int ContinueJump);
|
||||
void AddLoopControl(bool fBreak);
|
||||
friend class C4AulParseError;
|
||||
};
|
||||
|
||||
|
|
|
@ -179,6 +179,7 @@ protected:
|
|||
int GetCodePos() const { return Code.size(); }
|
||||
C4AulBCC *GetCodeByPos(int iPos) { return &Code[iPos]; }
|
||||
C4AulBCC *GetLastCode() { return Code.empty() ? NULL : &Code.back(); }
|
||||
void DumpByteCode();
|
||||
std::vector<C4AulBCC> Code;
|
||||
std::vector<const char *> PosForCode;
|
||||
int ParCount;
|
||||
|
@ -214,6 +215,7 @@ public:
|
|||
|
||||
uint32_t tProfileTime; // internally set by profiler
|
||||
|
||||
friend class C4CodeGen;
|
||||
friend class C4AulParse;
|
||||
friend class C4ScriptHost;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue