- process most of the remaining statement types.

- extend assignment operations to handle local variables (untested.)
- make the implicit function arguments read only.
This commit is contained in:
Christoph Oelckers 2016-10-21 01:12:54 +02:00
parent 24394dfc92
commit 9f99ca4788
8 changed files with 277 additions and 42 deletions

View file

@ -500,6 +500,18 @@ int PType::GetLoadOp() const
return OP_NOP; return OP_NOP;
} }
//==========================================================================
//
// PType :: GetMoveOp
//
//==========================================================================
int PType::GetMoveOp() const
{
assert(0 && "Cannot move this type");
return OP_NOP;
}
//========================================================================== //==========================================================================
// //
// PType :: GetRegType // PType :: GetRegType
@ -974,6 +986,17 @@ int PInt::GetLoadOp() const
} }
} }
//==========================================================================
//
// PInt :: GetLoadOp
//
//==========================================================================
int PInt::GetMoveOp() const
{
return OP_MOVE;
}
//========================================================================== //==========================================================================
// //
// PInt :: GetRegType // PInt :: GetRegType
@ -1271,6 +1294,17 @@ int PFloat::GetLoadOp() const
return OP_NOP; return OP_NOP;
} }
//==========================================================================
//
// PFloat :: GetMoveOp
//
//==========================================================================
int PFloat::GetMoveOp() const
{
return OP_MOVEF;
}
//========================================================================== //==========================================================================
// //
// PFloat :: GetRegType // PFloat :: GetRegType
@ -1540,6 +1574,17 @@ int PStatePointer::GetLoadOp() const
return OP_LP; return OP_LP;
} }
//==========================================================================
//
// PStatePointer :: GetMoveOp
//
//==========================================================================
int PStatePointer::GetMoveOp() const
{
return OP_MOVEA;
}
//========================================================================== //==========================================================================
// //
// PStatePointer :: GetRegType // PStatePointer :: GetRegType
@ -1627,6 +1672,17 @@ int PPointer::GetLoadOp() const
return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP; return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP;
} }
//==========================================================================
//
// PPointer :: GetMoveOp
//
//==========================================================================
int PPointer::GetMoveOp() const
{
return OP_MOVEA;
}
//========================================================================== //==========================================================================
// //
// PPointer :: GetRegType // PPointer :: GetRegType

View file

@ -28,7 +28,7 @@ enum
VARF_Final = (1<<9), // Function may not be overridden in subclasses VARF_Final = (1<<9), // Function may not be overridden in subclasses
VARF_In = (1<<10), VARF_In = (1<<10),
VARF_Out = (1<<11), VARF_Out = (1<<11),
VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare when checking function signatures) VARF_Implicit = (1<<12), // implicitly created parameters (i.e. do not compare types when checking function signatures)
VARF_Static = (1<<13), // static class data (by necessity read only.) VARF_Static = (1<<13), // static class data (by necessity read only.)
}; };
@ -272,6 +272,9 @@ public:
// Gets the opcode to load from memory to a register // Gets the opcode to load from memory to a register
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
// Gets the opcode to move from register to another register
virtual int GetMoveOp() const;
// Gets the register type for this type // Gets the register type for this type
virtual int GetRegType() const; virtual int GetRegType() const;
@ -409,6 +412,7 @@ public:
virtual double GetValueFloat(void *addr) const; virtual double GetValueFloat(void *addr) const;
virtual int GetStoreOp() const; virtual int GetStoreOp() const;
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
virtual int GetMoveOp() const;
virtual int GetRegType() const; virtual int GetRegType() const;
bool Unsigned; bool Unsigned;
@ -438,6 +442,7 @@ public:
virtual double GetValueFloat(void *addr) const; virtual double GetValueFloat(void *addr) const;
virtual int GetStoreOp() const; virtual int GetStoreOp() const;
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
virtual int GetMoveOp() const;
virtual int GetRegType() const; virtual int GetRegType() const;
protected: protected:
PFloat(); PFloat();
@ -516,6 +521,7 @@ public:
virtual int GetStoreOp() const; virtual int GetStoreOp() const;
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
virtual int GetMoveOp() const;
virtual int GetRegType() const; virtual int GetRegType() const;
}; };
@ -530,6 +536,7 @@ public:
virtual int GetStoreOp() const; virtual int GetStoreOp() const;
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
virtual int GetMoveOp() const;
virtual int GetRegType() const; virtual int GetRegType() const;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;

View file

@ -160,6 +160,18 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
} }
} }
FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
{
if (Block == nullptr)
{
return nullptr;
}
else
{
return Block->FindLocalVariable(name, *this);
}
}
//========================================================================== //==========================================================================
// //
// ExpEmit // ExpEmit
@ -1611,9 +1623,13 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
int zero = build->GetConstantInt(0); int zero = build->GetConstantInt(0);
int regtype = ValueType->GetRegType(); int regtype = ValueType->GetRegType();
ExpEmit pointer = Base->Emit(build); ExpEmit pointer = Base->Emit(build);
ExpEmit value = pointer;
ExpEmit value(build, regtype); if (!pointer.Target)
{
value = ExpEmit(build, regtype);
build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero); build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero);
}
if (regtype == REGT_INT) if (regtype == REGT_INT)
{ {
@ -1624,7 +1640,10 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.)); build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, value.RegNum, value.RegNum, build->GetConstantFloat(1.));
} }
if (!pointer.Target)
{
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero); build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero);
}
if (AddressRequested) if (AddressRequested)
{ {
@ -1690,9 +1709,13 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
int zero = build->GetConstantInt(0); int zero = build->GetConstantInt(0);
int regtype = ValueType->GetRegType(); int regtype = ValueType->GetRegType();
ExpEmit pointer = Base->Emit(build); ExpEmit pointer = Base->Emit(build);
ExpEmit out = pointer;
ExpEmit out(build, regtype); if (!pointer.Target)
{
out = ExpEmit(build, regtype);
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero); build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero);
}
ExpEmit assign(build, regtype); ExpEmit assign(build, regtype);
if (regtype == REGT_INT) if (regtype == REGT_INT)
@ -1704,7 +1727,10 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.)); build->Emit((Token == TK_Incr) ? OP_ADDF_RK : OP_SUBF_RK, assign.RegNum, out.RegNum, build->GetConstantFloat(1.));
} }
if (!pointer.Target)
{
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero); build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero);
}
pointer.Free(build); pointer.Free(build);
assign.Free(build); assign.Free(build);
@ -1781,6 +1807,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
ExpEmit FxAssign::Emit(VMFunctionBuilder *build) ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
{ {
static const BYTE loadops[] = { OP_NOP, OP_LK, OP_LKF, OP_LKS, OP_LKP };
assert(ValueType == Base->ValueType && IsNumeric()); assert(ValueType == Base->ValueType && IsNumeric());
assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
@ -1788,16 +1815,31 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
Address = pointer; Address = pointer;
ExpEmit result = Right->Emit(build); ExpEmit result = Right->Emit(build);
assert(result.RegType <= REGT_TYPE);
if (pointer.Target)
{
if (result.Konst)
{
build->Emit(loadops[result.RegType], pointer.RegNum, result.RegNum);
}
else
{
build->Emit(Right->ValueType->GetMoveOp(), pointer.RegNum, result.RegNum);
}
}
else
{
if (result.Konst) if (result.Konst)
{ {
ExpEmit temp(build, result.RegType); ExpEmit temp(build, result.RegType);
build->Emit(result.RegType == REGT_FLOAT ? OP_LKF : OP_LK, temp.RegNum, result.RegNum); build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
result.Free(build); result.Free(build);
result = temp; result = temp;
} }
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
}
if (AddressRequested) if (AddressRequested)
{ {
@ -1837,10 +1879,17 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build)
{ {
assert(ValueType = Assignment->ValueType); assert(ValueType = Assignment->ValueType);
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
if (!pointer.Target)
{
ExpEmit out(build, ValueType->GetRegType()); ExpEmit out(build, ValueType->GetRegType());
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
return out; return out;
} }
else
{
return pointer;
}
}
//========================================================================== //==========================================================================
// //
@ -3858,8 +3907,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
CHECKRESOLVED(); CHECKRESOLVED();
// Local variables have highest priority.
FxLocalVariableDeclaration *local = ctx.FindLocalVariable(Identifier);
if (local != nullptr)
{
auto x = new FxLocalVariable(local, ScriptPosition);
delete this;
return x->Resolve(ctx);
}
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here... // Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
// see if the current class (if valid) defines something with this name. // see if the current class (if valid) defines something with this name.
PSymbolTable *symtbl; PSymbolTable *symtbl;
if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr) if ((sym = ctx.FindInClass(Identifier, symtbl)) != nullptr)
@ -3959,6 +4015,40 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
} }
//==========================================================================
//
//
//
//==========================================================================
FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptPosition &sc)
: FxExpression(sc)
{
Variable = var;
AddressRequested = false;
}
FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
return this;
}
bool FxLocalVariable::RequestAddress(bool *writable)
{
AddressRequested = true;
if (writable != nullptr) *writable = !(Variable->VarFlags & VARF_ReadOnly);
return true;
}
ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build)
{
ExpEmit ret(Variable->RegNum, Variable->ValueType->GetRegType(), false, true);
if (AddressRequested) ret.Target = true;
return ret;
}
//========================================================================== //==========================================================================
// //
// //
@ -3998,9 +4088,7 @@ FxExpression *FxSelf::Resolve(FCompileContext& ctx)
ExpEmit FxSelf::Emit(VMFunctionBuilder *build) ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
{ {
// self is always the first pointer passed to the function // self is always the first pointer passed to the function
ExpEmit me(0, REGT_POINTER); return ExpEmit(0, REGT_POINTER, false, true);
me.Fixed = true;
return me;
} }
@ -6238,10 +6326,11 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build)
// //
//========================================================================== //==========================================================================
FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p) FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p)
:FxExpression(p) :FxExpression(p)
{ {
ValueType = type; ValueType = type;
VarFlags = varflags;
Name = name; Name = name;
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false); Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
} }

View file

@ -85,6 +85,7 @@ struct FCompileContext
void HandleJumps(int token, FxExpression *handler); void HandleJumps(int token, FxExpression *handler);
void CheckReturn(PPrototype *proto, FScriptPosition &pos); void CheckReturn(PPrototype *proto, FScriptPosition &pos);
FxLocalVariableDeclaration *FindLocalVariable(FName name);
}; };
//========================================================================== //==========================================================================
@ -198,7 +199,7 @@ struct ExpEmit
void Free(VMFunctionBuilder *build); void Free(VMFunctionBuilder *build);
void Reuse(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build);
BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1; BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1, Target:1;
}; };
//========================================================================== //==========================================================================
@ -964,6 +965,24 @@ public:
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
}; };
//==========================================================================
//
// FxLocalVariable
//
//==========================================================================
class FxLocalVariable : public FxExpression
{
public:
FxLocalVariableDeclaration *Variable;
bool AddressRequested;
FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&);
FxExpression *Resolve(FCompileContext&);
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
};
//========================================================================== //==========================================================================
// //
// FxSelf // FxSelf
@ -1382,13 +1401,15 @@ public:
class FxLocalVariableDeclaration : public FxExpression class FxLocalVariableDeclaration : public FxExpression
{ {
friend class FxCompoundStatement; friend class FxCompoundStatement;
friend class FxLocalVariable;
FName Name; FName Name;
FxExpression *Init; FxExpression *Init;
int VarFlags;
public: public:
int RegNum = -1; int RegNum = -1;
FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p); FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p);
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
void Release(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build);

View file

@ -90,7 +90,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
{ {
// implied self pointer // implied self pointer
if (args != nullptr) args->Push(NewPointer(cls)); if (args != nullptr) args->Push(NewPointer(cls));
if (argflags != nullptr) argflags->Push(VARF_Implicit); if (argflags != nullptr) argflags->Push(VARF_Implicit | VARF_ReadOnly);
if (argnames != nullptr) argnames->Push(NAME_self); if (argnames != nullptr) argnames->Push(NAME_self);
} }
if (funcflags & VARF_Action) if (funcflags & VARF_Action)
@ -111,8 +111,8 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
} }
if (argflags != nullptr) if (argflags != nullptr)
{ {
argflags->Push(VARF_Implicit); argflags->Push(VARF_Implicit | VARF_ReadOnly);
argflags->Push(VARF_Implicit); argflags->Push(VARF_Implicit | VARF_ReadOnly);
} }
if (argnames != nullptr) if (argnames != nullptr)
{ {

View file

@ -693,8 +693,9 @@ void FFunctionBuildList::Build()
{ {
auto type = item.Func->Variants[0].Proto->ArgumentTypes[i]; auto type = item.Func->Variants[0].Proto->ArgumentTypes[i];
auto name = item.Func->Variants[0].ArgNames[i]; auto name = item.Func->Variants[0].ArgNames[i];
// this won't get resolved and won't get emitted. This is only needed so that the code generator can retrieve the necessary info to do its work. auto flags = item.Func->Variants[0].ArgFlags[i];
auto local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition()); // this won't get resolved and won't get emitted. It is only needed so that the code generator can retrieve the necessary info about this argument to do its work.
auto local = new FxLocalVariableDeclaration(type, name, nullptr, flags, FScriptPosition());
local->RegNum = buildit.Registers[type->GetRegType()].Get(1); local->RegNum = buildit.Registers[type->GetRegType()].Get(1);
ctx.FunctionArgs.Push(local); ctx.FunctionArgs.Push(local);
} }

View file

@ -194,7 +194,7 @@ begin:
ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); ASSERTF(a+2); ASSERTA(B); ASSERTKD(C);
GETADDR(PB,KC,X_READ_NIL); GETADDR(PB,KC,X_READ_NIL);
{ {
float *v = (float *)ptr; auto v = (double *)ptr;
reg.f[a] = v[0]; reg.f[a] = v[0];
reg.f[a+1] = v[1]; reg.f[a+1] = v[1];
reg.f[a+2] = v[2]; reg.f[a+2] = v[2];
@ -204,7 +204,7 @@ begin:
ASSERTF(a+2); ASSERTA(B); ASSERTD(C); ASSERTF(a+2); ASSERTA(B); ASSERTD(C);
GETADDR(PB,RC,X_READ_NIL); GETADDR(PB,RC,X_READ_NIL);
{ {
float *v = (float *)ptr; auto v = (double *)ptr;
reg.f[a] = v[0]; reg.f[a] = v[0];
reg.f[a+1] = v[1]; reg.f[a+1] = v[1];
reg.f[a+2] = v[2]; reg.f[a+2] = v[2];
@ -290,20 +290,20 @@ begin:
ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); ASSERTA(a); ASSERTF(B+2); ASSERTKD(C);
GETADDR(PA,KC,X_WRITE_NIL); GETADDR(PA,KC,X_WRITE_NIL);
{ {
float *v = (float *)ptr; auto v = (double *)ptr;
v[0] = (float)reg.f[B]; v[0] = reg.f[B];
v[1] = (float)reg.f[B+1]; v[1] = reg.f[B+1];
v[2] = (float)reg.f[B+2]; v[2] = reg.f[B+2];
} }
NEXTOP; NEXTOP;
OP(SV_R): OP(SV_R):
ASSERTA(a); ASSERTF(B+2); ASSERTD(C); ASSERTA(a); ASSERTF(B+2); ASSERTD(C);
GETADDR(PA,RC,X_WRITE_NIL); GETADDR(PA,RC,X_WRITE_NIL);
{ {
float *v = (float *)ptr; auto v = (double *)ptr;
v[0] = (float)reg.f[B]; v[0] = reg.f[B];
v[1] = (float)reg.f[B+1]; v[1] = reg.f[B+1];
v[2] = (float)reg.f[B+2]; v[2] = reg.f[B+2];
} }
NEXTOP; NEXTOP;
OP(SBIT): OP(SBIT):

View file

@ -42,6 +42,7 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "m_alloc.h" #include "m_alloc.h"
#include "zcc_parser.h" #include "zcc_parser.h"
#include "zcc-parse.h"
#include "zcc_compile.h" #include "zcc_compile.h"
#include "v_text.h" #include "v_text.h"
#include "p_lnspec.h" #include "p_lnspec.h"
@ -2344,11 +2345,42 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
// The function name is a simple identifier. // The function name is a simple identifier.
return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast); return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast);
// not yet done
case AST_ExprTypeRef:
case AST_SwitchStmt:
case AST_CaseStmt:
case AST_ExprMemberAccess: case AST_ExprMemberAccess:
// calling a class member through its pointer // calling a class member through its pointer
// todo. // todo.
break; break;
case AST_AssignStmt:
{
auto assign = static_cast<ZCC_AssignStmt *>(ast);
switch (assign->AssignOp)
{
case ZCC_EQ:
// this ignores multi-assign statements (these should probably be disabled in the grammar.)
return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources));
case ZCC_MULEQ:
case ZCC_DIVEQ:
case ZCC_MODEQ:
case ZCC_ADDEQ:
case ZCC_SUBEQ:
case ZCC_LSHEQ:
case ZCC_RSHEQ:
case ZCC_ANDEQ:
case ZCC_OREQ:
case ZCC_XOREQ:
//break;
default:
Error(ast, "Invalid assign statement");
}
break;
}
case AST_ExprBinary: case AST_ExprBinary:
// Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side. // Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side.
if (fcall->Function->Operation == PEX_ArrayAccess) if (fcall->Function->Operation == PEX_ArrayAccess)
@ -2546,7 +2578,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
{ {
val = node->Init ? ConvertNode(node->Init) : nullptr; val = node->Init ? ConvertNode(node->Init) : nullptr;
} }
list->Add(new FxLocalVariableDeclaration(type, node->Name, val, *node)); list->Add(new FxLocalVariableDeclaration(type, node->Name, val, 0, *node)); // todo: Handle flags in the grammar.
} }
node = static_cast<decltype(node)>(node->SiblingNext); node = static_cast<decltype(node)>(node->SiblingNext);
@ -2576,6 +2608,35 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
} }
} }
case AST_BreakStmt:
case AST_ContinueStmt:
return new FxJumpStatement(ast->NodeType == AST_BreakStmt ? TK_Break : TK_Continue, *ast);
case AST_IfStmt:
{
auto iff = static_cast<ZCC_IfStmt *>(ast);
return new FxIfStatement(ConvertNode(iff->Condition), ConvertNode(iff->TruePath), ConvertNode(iff->FalsePath), *ast);
}
case AST_IterationStmt:
{
auto iter = static_cast<ZCC_IterationStmt *>(ast);
if (iter->CheckAt == ZCC_IterationStmt::End)
{
assert(iter->LoopBumper == nullptr);
return new FxDoWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast);
}
else if (iter->LoopBumper != nullptr)
{
return new FxForLoop(nullptr, ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopBumper), ConvertNode(iter->LoopStatement), *ast);
}
else
{
return new FxWhileLoop(ConvertNode(iter->LoopCondition), ConvertNode(iter->LoopStatement), *ast);
}
}
case AST_CompoundStmt: case AST_CompoundStmt:
{ {
auto x = new FxCompoundStatement(*ast); auto x = new FxCompoundStatement(*ast);