mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- 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:
parent
24394dfc92
commit
9f99ca4788
8 changed files with 277 additions and 42 deletions
|
@ -500,6 +500,18 @@ int PType::GetLoadOp() const
|
|||
return OP_NOP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType :: GetMoveOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PType::GetMoveOp() const
|
||||
{
|
||||
assert(0 && "Cannot move this type");
|
||||
return OP_NOP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType :: GetRegType
|
||||
|
@ -974,6 +986,17 @@ int PInt::GetLoadOp() const
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PInt :: GetLoadOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PInt::GetMoveOp() const
|
||||
{
|
||||
return OP_MOVE;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PInt :: GetRegType
|
||||
|
@ -1271,6 +1294,17 @@ int PFloat::GetLoadOp() const
|
|||
return OP_NOP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PFloat :: GetMoveOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PFloat::GetMoveOp() const
|
||||
{
|
||||
return OP_MOVEF;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PFloat :: GetRegType
|
||||
|
@ -1540,6 +1574,17 @@ int PStatePointer::GetLoadOp() const
|
|||
return OP_LP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: GetMoveOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PStatePointer::GetMoveOp() const
|
||||
{
|
||||
return OP_MOVEA;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStatePointer :: GetRegType
|
||||
|
@ -1627,6 +1672,17 @@ int PPointer::GetLoadOp() const
|
|||
return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PPointer :: GetMoveOp
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int PPointer::GetMoveOp() const
|
||||
{
|
||||
return OP_MOVEA;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PPointer :: GetRegType
|
||||
|
|
|
@ -28,7 +28,7 @@ enum
|
|||
VARF_Final = (1<<9), // Function may not be overridden in subclasses
|
||||
VARF_In = (1<<10),
|
||||
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.)
|
||||
};
|
||||
|
||||
|
@ -272,6 +272,9 @@ public:
|
|||
// Gets the opcode to load from memory to a register
|
||||
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
|
||||
virtual int GetRegType() const;
|
||||
|
||||
|
@ -409,6 +412,7 @@ public:
|
|||
virtual double GetValueFloat(void *addr) const;
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetMoveOp() const;
|
||||
virtual int GetRegType() const;
|
||||
|
||||
bool Unsigned;
|
||||
|
@ -438,6 +442,7 @@ public:
|
|||
virtual double GetValueFloat(void *addr) const;
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetMoveOp() const;
|
||||
virtual int GetRegType() const;
|
||||
protected:
|
||||
PFloat();
|
||||
|
@ -516,6 +521,7 @@ public:
|
|||
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetMoveOp() const;
|
||||
virtual int GetRegType() const;
|
||||
};
|
||||
|
||||
|
@ -530,6 +536,7 @@ public:
|
|||
|
||||
virtual int GetStoreOp() const;
|
||||
virtual int GetLoadOp() const;
|
||||
virtual int GetMoveOp() const;
|
||||
virtual int GetRegType() const;
|
||||
|
||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
|
|
|
@ -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
|
||||
|
@ -1611,9 +1623,13 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
int zero = build->GetConstantInt(0);
|
||||
int regtype = ValueType->GetRegType();
|
||||
ExpEmit pointer = Base->Emit(build);
|
||||
ExpEmit value = pointer;
|
||||
|
||||
ExpEmit value(build, regtype);
|
||||
build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero);
|
||||
if (!pointer.Target)
|
||||
{
|
||||
value = ExpEmit(build, regtype);
|
||||
build->Emit(ValueType->GetLoadOp(), value.RegNum, pointer.RegNum, zero);
|
||||
}
|
||||
|
||||
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(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero);
|
||||
if (!pointer.Target)
|
||||
{
|
||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, value.RegNum, zero);
|
||||
}
|
||||
|
||||
if (AddressRequested)
|
||||
{
|
||||
|
@ -1690,9 +1709,13 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build)
|
|||
int zero = build->GetConstantInt(0);
|
||||
int regtype = ValueType->GetRegType();
|
||||
ExpEmit pointer = Base->Emit(build);
|
||||
ExpEmit out = pointer;
|
||||
|
||||
ExpEmit out(build, regtype);
|
||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero);
|
||||
if (!pointer.Target)
|
||||
{
|
||||
out = ExpEmit(build, regtype);
|
||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, zero);
|
||||
}
|
||||
|
||||
ExpEmit assign(build, regtype);
|
||||
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(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero);
|
||||
if (!pointer.Target)
|
||||
{
|
||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, assign.RegNum, zero);
|
||||
}
|
||||
|
||||
pointer.Free(build);
|
||||
assign.Free(build);
|
||||
|
@ -1781,6 +1807,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
|||
|
||||
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->GetRegType() == Right->ValueType->GetRegType());
|
||||
|
||||
|
@ -1788,16 +1815,31 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
|||
Address = pointer;
|
||||
|
||||
ExpEmit result = Right->Emit(build);
|
||||
|
||||
if (result.Konst)
|
||||
{
|
||||
ExpEmit temp(build, result.RegType);
|
||||
build->Emit(result.RegType == REGT_FLOAT ? OP_LKF : OP_LK, temp.RegNum, result.RegNum);
|
||||
result.Free(build);
|
||||
result = temp;
|
||||
}
|
||||
assert(result.RegType <= REGT_TYPE);
|
||||
|
||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
||||
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)
|
||||
{
|
||||
ExpEmit temp(build, result.RegType);
|
||||
build->Emit(loadops[result.RegType], temp.RegNum, result.RegNum);
|
||||
result.Free(build);
|
||||
result = temp;
|
||||
}
|
||||
|
||||
build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0));
|
||||
}
|
||||
|
||||
if (AddressRequested)
|
||||
{
|
||||
|
@ -1837,9 +1879,16 @@ ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
assert(ValueType = Assignment->ValueType);
|
||||
ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it
|
||||
ExpEmit out(build, ValueType->GetRegType());
|
||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
||||
return out;
|
||||
if (!pointer.Target)
|
||||
{
|
||||
ExpEmit out(build, ValueType->GetRegType());
|
||||
build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0));
|
||||
return out;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3858,8 +3907,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
|
||||
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...
|
||||
|
||||
// see if the current class (if valid) defines something with this name.
|
||||
PSymbolTable *symtbl;
|
||||
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)
|
||||
{
|
||||
// self is always the first pointer passed to the function
|
||||
ExpEmit me(0, REGT_POINTER);
|
||||
me.Fixed = true;
|
||||
return me;
|
||||
return ExpEmit(0, REGT_POINTER, false, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
ValueType = type;
|
||||
VarFlags = varflags;
|
||||
Name = name;
|
||||
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ struct FCompileContext
|
|||
|
||||
void HandleJumps(int token, FxExpression *handler);
|
||||
void CheckReturn(PPrototype *proto, FScriptPosition &pos);
|
||||
FxLocalVariableDeclaration *FindLocalVariable(FName name);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -198,7 +199,7 @@ struct ExpEmit
|
|||
void Free(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);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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
|
||||
|
@ -1382,13 +1401,15 @@ public:
|
|||
class FxLocalVariableDeclaration : public FxExpression
|
||||
{
|
||||
friend class FxCompoundStatement;
|
||||
friend class FxLocalVariable;
|
||||
|
||||
FName Name;
|
||||
FxExpression *Init;
|
||||
int VarFlags;
|
||||
public:
|
||||
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&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void Release(VMFunctionBuilder *build);
|
||||
|
|
|
@ -90,7 +90,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
|||
{
|
||||
// implied self pointer
|
||||
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 (funcflags & VARF_Action)
|
||||
|
@ -111,8 +111,8 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
|||
}
|
||||
if (argflags != nullptr)
|
||||
{
|
||||
argflags->Push(VARF_Implicit);
|
||||
argflags->Push(VARF_Implicit);
|
||||
argflags->Push(VARF_Implicit | VARF_ReadOnly);
|
||||
argflags->Push(VARF_Implicit | VARF_ReadOnly);
|
||||
}
|
||||
if (argnames != nullptr)
|
||||
{
|
||||
|
|
|
@ -693,8 +693,9 @@ void FFunctionBuildList::Build()
|
|||
{
|
||||
auto type = item.Func->Variants[0].Proto->ArgumentTypes[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 local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition());
|
||||
auto flags = item.Func->Variants[0].ArgFlags[i];
|
||||
// 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);
|
||||
ctx.FunctionArgs.Push(local);
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ begin:
|
|||
ASSERTF(a+2); ASSERTA(B); ASSERTKD(C);
|
||||
GETADDR(PB,KC,X_READ_NIL);
|
||||
{
|
||||
float *v = (float *)ptr;
|
||||
auto v = (double *)ptr;
|
||||
reg.f[a] = v[0];
|
||||
reg.f[a+1] = v[1];
|
||||
reg.f[a+2] = v[2];
|
||||
|
@ -204,7 +204,7 @@ begin:
|
|||
ASSERTF(a+2); ASSERTA(B); ASSERTD(C);
|
||||
GETADDR(PB,RC,X_READ_NIL);
|
||||
{
|
||||
float *v = (float *)ptr;
|
||||
auto v = (double *)ptr;
|
||||
reg.f[a] = v[0];
|
||||
reg.f[a+1] = v[1];
|
||||
reg.f[a+2] = v[2];
|
||||
|
@ -290,20 +290,20 @@ begin:
|
|||
ASSERTA(a); ASSERTF(B+2); ASSERTKD(C);
|
||||
GETADDR(PA,KC,X_WRITE_NIL);
|
||||
{
|
||||
float *v = (float *)ptr;
|
||||
v[0] = (float)reg.f[B];
|
||||
v[1] = (float)reg.f[B+1];
|
||||
v[2] = (float)reg.f[B+2];
|
||||
auto v = (double *)ptr;
|
||||
v[0] = reg.f[B];
|
||||
v[1] = reg.f[B+1];
|
||||
v[2] = reg.f[B+2];
|
||||
}
|
||||
NEXTOP;
|
||||
OP(SV_R):
|
||||
ASSERTA(a); ASSERTF(B+2); ASSERTD(C);
|
||||
GETADDR(PA,RC,X_WRITE_NIL);
|
||||
{
|
||||
float *v = (float *)ptr;
|
||||
v[0] = (float)reg.f[B];
|
||||
v[1] = (float)reg.f[B+1];
|
||||
v[2] = (float)reg.f[B+2];
|
||||
auto v = (double *)ptr;
|
||||
v[0] = reg.f[B];
|
||||
v[1] = reg.f[B+1];
|
||||
v[2] = reg.f[B+2];
|
||||
}
|
||||
NEXTOP;
|
||||
OP(SBIT):
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "m_alloc.h"
|
||||
#include "zcc_parser.h"
|
||||
#include "zcc-parse.h"
|
||||
#include "zcc_compile.h"
|
||||
#include "v_text.h"
|
||||
#include "p_lnspec.h"
|
||||
|
@ -2344,11 +2345,42 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
// The function name is a simple identifier.
|
||||
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:
|
||||
// calling a class member through its pointer
|
||||
// todo.
|
||||
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:
|
||||
// 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)
|
||||
|
@ -2546,7 +2578,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
{
|
||||
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);
|
||||
|
@ -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:
|
||||
{
|
||||
auto x = new FxCompoundStatement(*ast);
|
||||
|
|
Loading…
Reference in a new issue